Merge "UM.getAliveUsers to exclude initialised ephemeral noncurrent users." into main
diff --git a/AconfigFlags.bp b/AconfigFlags.bp
index a42adad..0ccdf37 100644
--- a/AconfigFlags.bp
+++ b/AconfigFlags.bp
@@ -532,6 +532,7 @@
name: "android.content.pm.flags-aconfig",
package: "android.content.pm",
container: "system",
+ exportable: true,
srcs: ["core/java/android/content/pm/flags.aconfig"],
}
@@ -542,6 +543,18 @@
}
java_aconfig_library {
+ name: "android.content.pm.flags-aconfig-java-export",
+ aconfig_declarations: "android.content.pm.flags-aconfig",
+ defaults: ["framework-minus-apex-aconfig-java-defaults"],
+ mode: "exported",
+ min_sdk_version: "30",
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.permission",
+ ],
+}
+
+java_aconfig_library {
name: "android.content.pm.flags-aconfig-java-host",
aconfig_declarations: "android.content.pm.flags-aconfig",
host_supported: true,
@@ -1030,12 +1043,20 @@
name: "device_policy_aconfig_flags",
package: "android.app.admin.flags",
container: "system",
+ exportable: true,
srcs: [
"core/java/android/app/admin/flags/flags.aconfig",
],
}
java_aconfig_library {
+ name: "device_policy_exported_aconfig_flags_lib",
+ aconfig_declarations: "device_policy_aconfig_flags",
+ defaults: ["framework-minus-apex-aconfig-java-defaults"],
+ mode: "exported",
+}
+
+java_aconfig_library {
name: "device_policy_aconfig_flags_lib",
aconfig_declarations: "device_policy_aconfig_flags",
defaults: ["framework-minus-apex-aconfig-java-defaults"],
diff --git a/Ravenwood.bp b/Ravenwood.bp
index 74382a6..255ec92 100644
--- a/Ravenwood.bp
+++ b/Ravenwood.bp
@@ -30,7 +30,7 @@
name: "framework-minus-apex.ravenwood-base",
tools: ["hoststubgen"],
cmd: "$(location hoststubgen) " +
- "@$(location ravenwood/texts/ravenwood-standard-options.txt) " +
+ "@$(location :ravenwood-standard-options) " +
"--debug-log $(location hoststubgen_framework-minus-apex.log) " +
"--stats-file $(location hoststubgen_framework-minus-apex_stats.csv) " +
@@ -42,13 +42,13 @@
"--gen-input-dump-file $(location hoststubgen_dump.txt) " +
"--in-jar $(location :framework-minus-apex-for-hoststubgen) " +
- "--policy-override-file $(location ravenwood/texts/framework-minus-apex-ravenwood-policies.txt) " +
- "--annotation-allowed-classes-file $(location ravenwood/texts/ravenwood-annotation-allowed-classes.txt) ",
+ "--policy-override-file $(location :ravenwood-framework-policies) " +
+ "--annotation-allowed-classes-file $(location :ravenwood-annotation-allowed-classes) ",
srcs: [
":framework-minus-apex-for-hoststubgen",
- "ravenwood/texts/framework-minus-apex-ravenwood-policies.txt",
- "ravenwood/texts/ravenwood-standard-options.txt",
- "ravenwood/texts/ravenwood-annotation-allowed-classes.txt",
+ ":ravenwood-framework-policies",
+ ":ravenwood-standard-options",
+ ":ravenwood-annotation-allowed-classes",
],
out: [
"ravenwood.jar",
@@ -118,7 +118,7 @@
name: "services.core.ravenwood-base",
tools: ["hoststubgen"],
cmd: "$(location hoststubgen) " +
- "@$(location ravenwood/texts/ravenwood-standard-options.txt) " +
+ "@$(location :ravenwood-standard-options) " +
"--debug-log $(location hoststubgen_services.core.log) " +
"--stats-file $(location hoststubgen_services.core_stats.csv) " +
@@ -130,13 +130,13 @@
"--gen-input-dump-file $(location hoststubgen_dump.txt) " +
"--in-jar $(location :services.core-for-hoststubgen) " +
- "--policy-override-file $(location ravenwood/texts/services.core-ravenwood-policies.txt) " +
- "--annotation-allowed-classes-file $(location ravenwood/texts/ravenwood-annotation-allowed-classes.txt) ",
+ "--policy-override-file $(location :ravenwood-services-policies) " +
+ "--annotation-allowed-classes-file $(location :ravenwood-annotation-allowed-classes) ",
srcs: [
":services.core-for-hoststubgen",
- "ravenwood/texts/services.core-ravenwood-policies.txt",
- "ravenwood/texts/ravenwood-standard-options.txt",
- "ravenwood/texts/ravenwood-annotation-allowed-classes.txt",
+ ":ravenwood-services-policies",
+ ":ravenwood-standard-options",
+ ":ravenwood-annotation-allowed-classes",
],
out: [
"ravenwood.jar",
@@ -270,6 +270,7 @@
],
jni_libs: [
"libandroid_runtime",
+ "libravenwood_runtime",
],
}
diff --git a/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java b/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java
index 24d815f..e734174 100644
--- a/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java
+++ b/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java
@@ -427,6 +427,12 @@
*/
public static final int REASON_PACKAGE_UNARCHIVE = 328;
+ /**
+ * Tile onClick event
+ * @hide
+ */
+ public static final int REASON_TILE_ONCLICK = 329;
+
/** @hide The app requests out-out. */
public static final int REASON_OPT_OUT_REQUESTED = 1000;
@@ -504,13 +510,15 @@
REASON_ROLE_EMERGENCY,
REASON_SYSTEM_MODULE,
REASON_CARRIER_PRIVILEGED_APP,
- REASON_OPT_OUT_REQUESTED,
REASON_DPO_PROTECTED_APP,
REASON_DISALLOW_APPS_CONTROL,
REASON_ACTIVE_DEVICE_ADMIN,
REASON_MEDIA_NOTIFICATION_TRANSFER,
REASON_PACKAGE_INSTALLER,
+ REASON_SYSTEM_EXEMPT_APP_OP,
REASON_PACKAGE_UNARCHIVE,
+ REASON_TILE_ONCLICK,
+ REASON_OPT_OUT_REQUESTED,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ReasonCode {}
diff --git a/apex/jobscheduler/framework/java/android/os/PowerWhitelistManager.java b/apex/jobscheduler/framework/java/android/os/PowerWhitelistManager.java
index 20da171..18ffb7a 100644
--- a/apex/jobscheduler/framework/java/android/os/PowerWhitelistManager.java
+++ b/apex/jobscheduler/framework/java/android/os/PowerWhitelistManager.java
@@ -310,6 +310,11 @@
* @hide
*/
public static final int REASON_SHELL = PowerExemptionManager.REASON_SHELL;
+ /**
+ * Tile onClick event
+ * @hide
+ */
+ public static final int REASON_TILE_ONCLICK = PowerExemptionManager.REASON_TILE_ONCLICK;
/**
* The list of BG-FGS-Launch and temp-allowlist reason code.
diff --git a/api/StubLibraries.bp b/api/StubLibraries.bp
index f56a950..9b81bd4 100644
--- a/api/StubLibraries.bp
+++ b/api/StubLibraries.bp
@@ -1144,31 +1144,47 @@
],
}
-droidstubs {
- name: "api_versions_public",
- srcs: [":android_stubs_current_with_test_libs{.jar}"],
+// Defaults for `droidstubs` modules that generate `api-versions.xml` files for
+// the various API surfaces.
+stubs_defaults {
+ name: "api_versions_base_defaults",
+ defaults_visibility: ["//visibility:private"],
generate_stubs: false,
api_levels_annotations_enabled: true,
api_levels_annotations_dirs: [
"sdk-dir",
"api-versions-jars-dir",
],
- api_levels_sdk_type: "public",
+}
+
+// Defaults for `droidstubs` modules that generate complete `api-versions.xml`
+// files, i.e. include SDK extensions.
+stubs_defaults {
+ name: "api_versions_complete_defaults",
+ defaults_visibility: ["//visibility:private"],
+ defaults: ["api_versions_base_defaults"],
extensions_info_file: ":sdk-extensions-info",
+}
+
+// Produces an `api-versions.xml` file that includes up-to-date information
+// about all the public APIs, both updatable and non-updatable and historic
+// information about all previous dessert and SDK extension releases.
+droidstubs {
+ name: "api_versions_public",
+ defaults: ["api_versions_complete_defaults"],
+ srcs: [":android_stubs_current_with_test_libs{.jar}"],
+ api_levels_sdk_type: "public",
visibility: ["//frameworks/base"],
}
+// Produces an `api-versions.xml` file that includes up-to-date information
+// about all the system APIs, both updatable and non-updatable and historic
+// information about all previous dessert and SDK extension releases.
droidstubs {
name: "api_versions_system",
+ defaults: ["api_versions_complete_defaults"],
srcs: [":android_system_stubs_current_with_test_libs{.jar}"],
- generate_stubs: false,
- api_levels_annotations_enabled: true,
- api_levels_annotations_dirs: [
- "sdk-dir",
- "api-versions-jars-dir",
- ],
api_levels_sdk_type: "system",
- extensions_info_file: ":sdk-extensions-info",
dists: [
// Make the api-versions.xml file for the system API available in the
// sdk build target.
@@ -1180,42 +1196,99 @@
],
}
-// This module can be built with:
-// m out/soong/.intermediates/frameworks/base/api/api_versions_module_lib/android_common/metalava/api-versions.xml
-droidstubs {
- name: "api_versions_module_lib",
- srcs: [":android_module_stubs_current_with_test_libs{.jar}"],
- generate_stubs: false,
- api_levels_annotations_enabled: true,
+// Defaults for `droidstubs` modules that generate `api-versions.xml` files that
+// only include non-updatable code, i.e. for platform API only, not SDK
+// extensions.
+stubs_defaults {
+ name: "api_versions_non_updatable_defaults",
+ defaults_visibility: ["//visibility:private"],
+ defaults: ["api_versions_base_defaults"],
// this only has the non-updatable portions of the module lib sdk,
// which can reference classes from updatable apexes, so remove references to them
// from this api_versions file.
flags: ["--remove-missing-class-references-in-api-levels"],
- api_levels_annotations_dirs: [
- "sdk-dir",
- "api-versions-jars-dir",
- ],
- api_levels_sdk_type: "module-lib",
// extensions_info_file is purposefully omitted, because this module should just be
// the non-updatable portions of the sdk, and extension sdks are updatable.
}
+// Produces an `api-versions.xml` file that includes up-to-date information
+// about only the non-updatable module-lib APIs and historic information about
+// all previous dessert and SDK extension releases. That historic information
+// may include information about APIs that were previously not-updatable which
+// have since become updatable.
+droidstubs {
+ name: "api_versions_module_lib",
+ defaults: ["api_versions_non_updatable_defaults"],
+ srcs: [":android_module_stubs_current_with_test_libs{.jar}"],
+ api_levels_sdk_type: "module-lib",
+}
+
+// Create a single jar containing the whole module-lib API surface.
+// This is needed because Metalava only consumes the first jar file it is given
+// and ignores the rest.
+java_library {
+ name: "android_module_stubs_complete_current_with_test_libs",
+ static_libs: [
+ "android_module_stubs_current_with_test_libs",
+ "framework-updatable-stubs-module_libs_api-exportable",
+ ],
+ defaults: ["android.jar_defaults"],
+ visibility: [
+ "//visibility:override",
+ "//visibility:private",
+ ],
+}
+
+// Produces an `api-versions.xml` file that includes up-to-date information
+// about all the module-lib APIs, both updatable and non-updatable and historic
+// information about all previous dessert and SDK extension releases.
+droidstubs {
+ name: "api_versions_module_lib_complete",
+ defaults: ["api_versions_complete_defaults"],
+ srcs: [":android_module_stubs_complete_current_with_test_libs{.jar}"],
+ api_levels_sdk_type: "module-lib",
+}
+
+// Produces an `api-versions.xml` file that includes up-to-date information
+// about only the non-updatable system-server APIs and historic information
+// about all previous dessert and SDK extension releases. That historic
+// information may include information about APIs that were previously
+// not-updatable which have since become updatable.
droidstubs {
name: "api_versions_system_server",
+ defaults: ["api_versions_non_updatable_defaults"],
srcs: [":android_system_server_stubs_current_with_test_libs{.jar}"],
- generate_stubs: false,
- api_levels_annotations_enabled: true,
- // this only has the non-updatable portions of the system server sdk,
- // which can reference classes from updatable apexes, so remove references to them
- // from this api_versions file.
- flags: ["--remove-missing-class-references-in-api-levels"],
- api_levels_annotations_dirs: [
- "sdk-dir",
- "api-versions-jars-dir",
- ],
api_levels_sdk_type: "system-server",
- // extensions_info_file is purposefully omitted, because this module should just be
- // the non-updatable portions of the sdk, and extension sdks are updatable.
+}
+
+// Create a single jar containing the whole system-server API surface.
+// This is needed because Metalava only consumes the first jar file it is given
+// and ignores the rest.
+java_library {
+ name: "android_system_server_stubs_complete_current_with_test_libs",
+ static_libs: [
+ "android_system_server_stubs_current_with_test_libs",
+ // system-server extends module-lib but libraries which only service-*
+ // libraries provided system-server APIs, so include module-lib APIs for
+ // the others, e.g. framework-* libraries.
+ "framework-updatable-stubs-module_libs_api-exportable",
+ "framework-updatable-stubs-system_server_api-exportable",
+ ],
+ defaults: ["android.jar_defaults"],
+ visibility: [
+ "//visibility:override",
+ "//visibility:private",
+ ],
+}
+
+// Produces an `api-versions.xml` file that includes up-to-date information
+// about all the system-server APIs, both updatable and non-updatable and
+// historic information about all previous dessert and SDK extension releases.
+droidstubs {
+ name: "api_versions_system_server_complete",
+ defaults: ["api_versions_complete_defaults"],
+ srcs: [":android_system_server_stubs_complete_current_with_test_libs{.jar}"],
+ api_levels_sdk_type: "system-server",
}
/////////////////////////////////////////////////////////////////////
diff --git a/api/api.go b/api/api.go
index b31a26c..449fac6 100644
--- a/api/api.go
+++ b/api/api.go
@@ -386,6 +386,26 @@
ctx.CreateModule(java.LibraryFactory, &props)
}
+func createMergedFrameworkSystemServerExportableStubs(ctx android.LoadHookContext, bootclasspath, system_server_classpath []string) {
+ // The user of this module compiles against the "core" SDK and against non-updatable bootclasspathModules,
+ // so remove to avoid dupes.
+ bootclasspathModules := removeAll(bootclasspath, core_libraries_modules)
+ bootclasspathModules = removeAll(bootclasspath, non_updatable_modules)
+ modules := append(
+ // Include all the module-lib APIs from the bootclasspath libraries.
+ transformArray(bootclasspathModules, "", ".stubs.exportable.module_lib"),
+ // Then add all the system-server APIs from the service-* libraries.
+ transformArray(system_server_classpath, "", ".stubs.exportable.system_server")...,
+ )
+ props := libraryProps{}
+ props.Name = proptools.StringPtr("framework-updatable-stubs-system_server_api-exportable")
+ props.Static_libs = modules
+ props.Sdk_version = proptools.StringPtr("system_server_current")
+ props.Visibility = []string{"//frameworks/base"}
+ props.Is_stubs_module = proptools.BoolPtr(true)
+ ctx.CreateModule(java.LibraryFactory, &props)
+}
+
func createPublicStubsSourceFilegroup(ctx android.LoadHookContext, modules []string) {
props := fgProps{}
props.Name = proptools.StringPtr("all-modules-public-stubs-source")
@@ -531,6 +551,7 @@
createMergedSystemExportableStubs(ctx, bootclasspath)
createMergedTestExportableStubsForNonUpdatableModules(ctx)
createMergedFrameworkModuleLibExportableStubs(ctx, bootclasspath)
+ createMergedFrameworkSystemServerExportableStubs(ctx, bootclasspath, system_server_classpath)
createMergedAnnotationsFilegroups(ctx, bootclasspath, system_server_classpath)
diff --git a/config/Android.bp b/config/Android.bp
index adce203..c9948c3 100644
--- a/config/Android.bp
+++ b/config/Android.bp
@@ -33,7 +33,7 @@
name: "preloaded-classes",
src: "preloaded-classes",
filename: "preloaded-classes",
- installable: false,
+ no_full_install: true,
}
filegroup {
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 0372b7b..2437be8 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -1529,9 +1529,9 @@
package android.hardware {
@Deprecated public class Camera {
- method @Deprecated public static void getCameraInfo(int, @NonNull android.content.Context, boolean, android.hardware.Camera.CameraInfo);
+ method @Deprecated public static void getCameraInfo(int, @NonNull android.content.Context, int, android.hardware.Camera.CameraInfo);
method @Deprecated public static int getNumberOfCameras(@NonNull android.content.Context);
- method @Deprecated public static android.hardware.Camera open(int, @NonNull android.content.Context, boolean);
+ method @Deprecated public static android.hardware.Camera open(int, @NonNull android.content.Context, int);
method @Deprecated public final void setPreviewSurface(android.view.Surface) throws java.io.IOException;
}
@@ -1606,11 +1606,15 @@
public final class CameraManager {
method @NonNull public android.hardware.camera2.CameraCharacteristics getCameraCharacteristics(@NonNull String, boolean) throws android.hardware.camera2.CameraAccessException;
method public String[] getCameraIdListNoLazy() throws android.hardware.camera2.CameraAccessException;
+ method @FlaggedApi("com.android.window.flags.camera_compat_for_freeform") public static int getRotationOverrideInternal(@Nullable android.content.Context, @Nullable android.content.pm.PackageManager, @Nullable String);
method @RequiresPermission(android.Manifest.permission.CAMERA) public void openCamera(@NonNull String, boolean, @Nullable android.os.Handler, @NonNull android.hardware.camera2.CameraDevice.StateCallback) throws android.hardware.camera2.CameraAccessException;
method @RequiresPermission(allOf={android.Manifest.permission.SYSTEM_CAMERA, android.Manifest.permission.CAMERA}) public void openCamera(@NonNull String, int, @NonNull java.util.concurrent.Executor, @NonNull android.hardware.camera2.CameraDevice.StateCallback) throws android.hardware.camera2.CameraAccessException;
method public static boolean shouldOverrideToPortrait(@Nullable android.content.pm.PackageManager, @Nullable String);
field public static final String LANDSCAPE_TO_PORTRAIT_PROP = "camera.enable_landscape_to_portrait";
field public static final long OVERRIDE_CAMERA_LANDSCAPE_TO_PORTRAIT = 250678880L; // 0xef10e60L
+ field @FlaggedApi("com.android.window.flags.camera_compat_for_freeform") public static final int ROTATION_OVERRIDE_NONE = 0; // 0x0
+ field @FlaggedApi("com.android.window.flags.camera_compat_for_freeform") public static final int ROTATION_OVERRIDE_OVERRIDE_TO_PORTRAIT = 1; // 0x1
+ field @FlaggedApi("com.android.window.flags.camera_compat_for_freeform") public static final int ROTATION_OVERRIDE_ROTATION_ONLY = 2; // 0x2
}
public abstract static class CameraManager.AvailabilityCallback {
@@ -3989,15 +3993,15 @@
method @RequiresPermission(android.Manifest.permission.TEST_INPUT_METHOD) public void addVirtualStylusIdForTestSession();
method @RequiresPermission(android.Manifest.permission.TEST_INPUT_METHOD) public void finishTrackingPendingImeVisibilityRequests();
method public int getDisplayId();
- method @FlaggedApi("android.view.inputmethod.imm_userhandle_hostsidetests") @NonNull @RequiresPermission(value=android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, conditional=true) public java.util.List<android.view.inputmethod.InputMethodInfo> getEnabledInputMethodListAsUser(@NonNull android.os.UserHandle);
- method @FlaggedApi("android.view.inputmethod.imm_userhandle_hostsidetests") @NonNull @RequiresPermission(value=android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, conditional=true) public java.util.List<android.view.inputmethod.InputMethodSubtype> getEnabledInputMethodSubtypeListAsUser(@NonNull String, boolean, @NonNull android.os.UserHandle);
+ method @NonNull @RequiresPermission(value=android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, conditional=true) public java.util.List<android.view.inputmethod.InputMethodInfo> getEnabledInputMethodListAsUser(@NonNull android.os.UserHandle);
+ method @NonNull @RequiresPermission(value=android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, conditional=true) public java.util.List<android.view.inputmethod.InputMethodSubtype> getEnabledInputMethodSubtypeListAsUser(@NonNull String, boolean, @NonNull android.os.UserHandle);
method @NonNull @RequiresPermission(value=android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, conditional=true) public java.util.List<android.view.inputmethod.InputMethodInfo> getInputMethodListAsUser(int);
method public boolean hasActiveInputConnection(@Nullable android.view.View);
method @RequiresPermission(android.Manifest.permission.TEST_INPUT_METHOD) public boolean hasPendingImeVisibilityRequests();
method @RequiresPermission(android.Manifest.permission.TEST_INPUT_METHOD) public void hideSoftInputFromServerForTest();
method @RequiresPermission(android.Manifest.permission.TEST_INPUT_METHOD) public boolean isCurrentRootView(@NonNull android.view.View);
method @RequiresPermission(android.Manifest.permission.TEST_INPUT_METHOD) public boolean isInputMethodPickerShown();
- method @FlaggedApi("android.view.inputmethod.imm_userhandle_hostsidetests") @NonNull @RequiresPermission(value=android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, conditional=true) public boolean isStylusHandwritingAvailableAsUser(@NonNull android.os.UserHandle);
+ method @NonNull @RequiresPermission(value=android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, conditional=true) public boolean isStylusHandwritingAvailableAsUser(@NonNull android.os.UserHandle);
method @RequiresPermission(android.Manifest.permission.TEST_INPUT_METHOD) public void setStylusWindowIdleTimeoutForTest(long);
field public static final long CLEAR_SHOW_FORCED_FLAG_WHEN_LEAVING = 214016041L; // 0xcc1a029L
}
diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
index dc5c7f6..713d8e5 100644
--- a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
+++ b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
@@ -43,131 +43,189 @@
*/
interface IAccessibilityServiceConnection {
+ @RequiresNoPermission
void setServiceInfo(in AccessibilityServiceInfo info);
+ @RequiresNoPermission
void setAttributionTag(in String attributionTag);
+ @RequiresNoPermission
String[] findAccessibilityNodeInfoByAccessibilityId(int accessibilityWindowId,
long accessibilityNodeId, int interactionId,
IAccessibilityInteractionConnectionCallback callback, int flags, long threadId,
in Bundle arguments);
+ @RequiresNoPermission
String[] findAccessibilityNodeInfosByText(int accessibilityWindowId, long accessibilityNodeId,
String text, int interactionId, IAccessibilityInteractionConnectionCallback callback,
long threadId);
+ @RequiresNoPermission
String[] findAccessibilityNodeInfosByViewId(int accessibilityWindowId,
long accessibilityNodeId, String viewId, int interactionId,
IAccessibilityInteractionConnectionCallback callback, long threadId);
+ @RequiresNoPermission
String[] findFocus(int accessibilityWindowId, long accessibilityNodeId, int focusType,
int interactionId, IAccessibilityInteractionConnectionCallback callback, long threadId);
+ @RequiresNoPermission
String[] focusSearch(int accessibilityWindowId, long accessibilityNodeId, int direction,
int interactionId, IAccessibilityInteractionConnectionCallback callback, long threadId);
+ @RequiresNoPermission
boolean performAccessibilityAction(int accessibilityWindowId, long accessibilityNodeId,
int action, in Bundle arguments, int interactionId,
IAccessibilityInteractionConnectionCallback callback, long threadId);
+ @RequiresNoPermission
AccessibilityWindowInfo getWindow(int windowId);
+ @RequiresNoPermission
AccessibilityWindowInfo.WindowListSparseArray getWindows();
+ @RequiresNoPermission
AccessibilityServiceInfo getServiceInfo();
+ @RequiresNoPermission
boolean performGlobalAction(int action);
+
+ @RequiresNoPermission
List<AccessibilityNodeInfo.AccessibilityAction> getSystemActions();
+ @RequiresNoPermission
void disableSelf();
+ @RequiresNoPermission
oneway void setOnKeyEventResult(boolean handled, int sequence);
+ @RequiresNoPermission
MagnificationConfig getMagnificationConfig(int displayId);
+ @RequiresNoPermission
float getMagnificationScale(int displayId);
+ @RequiresNoPermission
float getMagnificationCenterX(int displayId);
+ @RequiresNoPermission
float getMagnificationCenterY(int displayId);
+ @RequiresNoPermission
Region getMagnificationRegion(int displayId);
+ @RequiresNoPermission
Region getCurrentMagnificationRegion(int displayId);
+ @RequiresNoPermission
boolean resetMagnification(int displayId, boolean animate);
+ @RequiresNoPermission
boolean resetCurrentMagnification(int displayId, boolean animate);
+ @RequiresNoPermission
boolean setMagnificationConfig(int displayId, in MagnificationConfig config, boolean animate);
+ @RequiresNoPermission
void setMagnificationCallbackEnabled(int displayId, boolean enabled);
+ @RequiresNoPermission
boolean setSoftKeyboardShowMode(int showMode);
+ @RequiresNoPermission
int getSoftKeyboardShowMode();
+ @RequiresNoPermission
void setSoftKeyboardCallbackEnabled(boolean enabled);
- boolean switchToInputMethod(String imeId);
+ @RequiresNoPermission
+ boolean switchToInputMethod(String imeId);
- int setInputMethodEnabled(String imeId, boolean enabled);
+ @RequiresNoPermission
+ int setInputMethodEnabled(String imeId, boolean enabled);
+ @RequiresNoPermission
boolean isAccessibilityButtonAvailable();
+ @RequiresNoPermission
void sendGesture(int sequence, in ParceledListSlice gestureSteps);
+ @RequiresNoPermission
void dispatchGesture(int sequence, in ParceledListSlice gestureSteps, int displayId);
+ @RequiresNoPermission
boolean isFingerprintGestureDetectionAvailable();
+ @RequiresNoPermission
IBinder getOverlayWindowToken(int displayid);
+ @RequiresNoPermission
int getWindowIdForLeashToken(IBinder token);
+ @RequiresNoPermission
void takeScreenshot(int displayId, in RemoteCallback callback);
+ @RequiresNoPermission
void takeScreenshotOfWindow(int accessibilityWindowId, int interactionId,
in ScreenCapture.ScreenCaptureListener listener,
IAccessibilityInteractionConnectionCallback callback);
+ @RequiresNoPermission
void setGestureDetectionPassthroughRegion(int displayId, in Region region);
+ @RequiresNoPermission
void setTouchExplorationPassthroughRegion(int displayId, in Region region);
+ @RequiresNoPermission
void setFocusAppearance(int strokeWidth, int color);
+ @RequiresNoPermission
void setCacheEnabled(boolean enabled);
+ @RequiresNoPermission
oneway void logTrace(long timestamp, String where, long loggingTypes, String callingParams,
int processId, long threadId, int callingUid, in Bundle serializedCallingStackInBundle);
+ @RequiresNoPermission
void setServiceDetectsGesturesEnabled(int displayId, boolean mode);
+ @RequiresNoPermission
void requestTouchExploration(int displayId);
+ @RequiresNoPermission
void requestDragging(int displayId, int pointerId);
+ @RequiresNoPermission
void requestDelegating(int displayId);
+ @RequiresNoPermission
void onDoubleTap(int displayId);
+ @RequiresNoPermission
void onDoubleTapAndHold(int displayId);
+ @RequiresNoPermission
void setAnimationScale(float scale);
+ @RequiresNoPermission
void setInstalledAndEnabledServices(in List<AccessibilityServiceInfo> infos);
- List<AccessibilityServiceInfo> getInstalledAndEnabledServices();
+ @RequiresNoPermission
+ List<AccessibilityServiceInfo> getInstalledAndEnabledServices();
+
+ @RequiresNoPermission
void attachAccessibilityOverlayToDisplay(int interactionId, int displayId, in SurfaceControl sc, IAccessibilityInteractionConnectionCallback callback);
+ @RequiresNoPermission
void attachAccessibilityOverlayToWindow(int interactionId, int accessibilityWindowId, in SurfaceControl sc, IAccessibilityInteractionConnectionCallback callback);
- @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)")
+ @EnforcePermission("BLUETOOTH_CONNECT")
void connectBluetoothBrailleDisplay(in String bluetoothAddress, in IBrailleDisplayController controller);
+
+ @RequiresNoPermission
void connectUsbBrailleDisplay(in UsbDevice usbDevice, in IBrailleDisplayController controller);
- @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.MANAGE_ACCESSIBILITY)")
+ @EnforcePermission("MANAGE_ACCESSIBILITY")
void setTestBrailleDisplayData(in List<Bundle> brailleDisplays);
}
\ No newline at end of file
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 5e9fdfb..1e824a1 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -6257,6 +6257,29 @@
* {@link #RESTRICTION_LEVEL_ADAPTIVE} is a normal state, where there is default lifecycle
* management applied to the app. Also, {@link #RESTRICTION_LEVEL_EXEMPTED} is used when the
* app is being put in a power-save allowlist.
+ * <p>
+ * Example arguments when user force-stops an app from Settings:
+ * <pre>
+ * noteAppRestrictionEnabled(
+ * "com.example.app",
+ * appUid,
+ * RESTRICTION_LEVEL_FORCE_STOPPED,
+ * true,
+ * RESTRICTION_REASON_USER,
+ * "settings",
+ * 0);
+ * </pre>
+ * Example arguments when app is put in restricted standby bucket for exceeding X hours of jobs:
+ * <pre>
+ * noteAppRestrictionEnabled(
+ * "com.example.app",
+ * appUid,
+ * RESTRICTION_LEVEL_RESTRICTED_BUCKET,
+ * true,
+ * RESTRICTION_REASON_SYSTEM_HEALTH,
+ * "job_duration",
+ * X * 3600 * 1000L);
+ * </pre>
*
* @param packageName the package name of the app
* @param uid the uid of the app
@@ -6264,11 +6287,20 @@
* @param enabled whether the state is being applied or removed
* @param reason the reason for the restriction state change, from {@code RestrictionReason}
* @param subReason a string sub reason limited to 16 characters that specifies additional
- * information about the reason for restriction.
+ * information about the reason for restriction. This string must only contain
+ * reasons related to excessive system resource usage or in some cases,
+ * source of the restriction. This string must not contain any details that
+ * identify user behavior beyond their actions to restrict/unrestrict/launch
+ * apps in some way.
+ * Examples of system resource usage: wakelock, wakeups, mobile_data,
+ * binder_calls, memory, excessive_threads, excessive_cpu, gps_scans, etc.
+ * Examples of user actions: settings, notification, command_line, launch, etc.
+ *
* @param threshold for reasons that are due to exceeding some threshold, the threshold value
* must be specified. The unit of the threshold depends on the reason and/or
* subReason. For time, use milliseconds. For memory, use KB. For count, use
- * the actual count or normalized as per-hour. For power, use milliwatts. Etc.
+ * the actual count or if rate limited, normalized per-hour. For power,
+ * use milliwatts. For CPU, use mcycles.
*
* @hide
*/
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index e66f7fe..d8df447 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -1270,4 +1270,16 @@
* @hide
*/
public abstract boolean shouldDelayHomeLaunch(int userId);
+
+ /**
+ * Add a startup timestamp to the most recent start of the specified process.
+ *
+ * @param key The {@link ApplicationStartInfo} start timestamp key of the timestamp to add.
+ * @param timestampNs The clock monotonic timestamp to add in nanoseconds.
+ * @param uid The UID of the process to add this timestamp to.
+ * @param pid The process id of the process to add this timestamp to.
+ * @param userId The userId in the multi-user environment.
+ */
+ public abstract void addStartInfoTimestamp(int key, long timestampNs, int uid, int pid,
+ int userId);
}
diff --git a/core/java/android/app/ActivityTaskManager.java b/core/java/android/app/ActivityTaskManager.java
index be8f48d..c8ab260 100644
--- a/core/java/android/app/ActivityTaskManager.java
+++ b/core/java/android/app/ActivityTaskManager.java
@@ -90,13 +90,6 @@
public static final int RESIZE_MODE_USER = RESIZE_MODE_PRESERVE_WINDOW;
/**
- * Input parameter to {@link IActivityTaskManager#resizeTask} used by window
- * manager during a screen rotation.
- * @hide
- */
- public static final int RESIZE_MODE_SYSTEM_SCREEN_ROTATION = RESIZE_MODE_PRESERVE_WINDOW;
-
- /**
* Input parameter to {@link IActivityTaskManager#resizeTask} which indicates
* that the resize should be performed even if the bounds appears unchanged.
* @hide
diff --git a/core/java/android/app/GrammaticalInflectionManager.java b/core/java/android/app/GrammaticalInflectionManager.java
index f0bc3e2..37e51f8 100644
--- a/core/java/android/app/GrammaticalInflectionManager.java
+++ b/core/java/android/app/GrammaticalInflectionManager.java
@@ -104,7 +104,7 @@
* Sets the current grammatical gender for all privileged applications. The value will be
* stored in an encrypted file at {@link android.os.Environment#getDataSystemCeDirectory(int)}
*
- * @param grammaticalGender the terms of address the user preferred in system.
+ * @param grammaticalGender the grammatical gender set by the user for the system.
*
* @see Configuration#getGrammaticalGender
* @hide
@@ -123,12 +123,12 @@
}
/**
- * Get the current grammatical gender of privileged application from the encrypted file.
+ * Allows privileged preloaded applications to get the system grammatical gender when set.
*
- * @return the value of system grammatical gender only if the calling app has the permission,
- * otherwise throwing an exception.
+ * @return The value of system grammatical gender only if the calling app has the
+ * permission, otherwise throwing an exception.
*
- * @throws SecurityException if the caller does not have the required permission.
+ * @throws SecurityException If the caller does not have the required permission.
*
* @see Configuration#getGrammaticalGender
*/
diff --git a/core/java/android/app/ITaskStackListener.aidl b/core/java/android/app/ITaskStackListener.aidl
index 3c6ff28..f2228f9 100644
--- a/core/java/android/app/ITaskStackListener.aidl
+++ b/core/java/android/app/ITaskStackListener.aidl
@@ -145,6 +145,11 @@
void onTaskSnapshotChanged(int taskId, in TaskSnapshot snapshot);
/**
+ * Called when a task snapshot become invalidated.
+ */
+ void onTaskSnapshotInvalidated(int taskId);
+
+ /**
* Reports that an Activity received a back key press when there were no additional activities
* on the back stack.
*
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 25dbedc..3c402ca 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -3259,8 +3259,9 @@
boolean mustClearCookie = false;
if (!parcel.hasClassCookie(Notification.class)) {
// This is the "root" notification, and not an "inner" notification (including
- // publicVersion or anything else that might be embedded in extras).
- parcel.setClassCookie(Notification.class, this);
+ // publicVersion or anything else that might be embedded in extras). So we want
+ // to use its token for every inner notification (might be null).
+ parcel.setClassCookie(Notification.class, mAllowlistToken);
mustClearCookie = true;
}
try {
@@ -3269,7 +3270,7 @@
writeToParcelImpl(parcel, flags);
} finally {
if (mustClearCookie) {
- parcel.removeClassCookie(Notification.class, this);
+ parcel.removeClassCookie(Notification.class, mAllowlistToken);
}
}
} else {
@@ -3293,14 +3294,9 @@
parcel.writeInt(1);
if (Flags.secureAllowlistToken()) {
- Notification rootNotification = (Notification) parcel.getClassCookie(
- Notification.class);
- if (rootNotification != null && rootNotification != this) {
- // Always use the same token as the root notification
- parcel.writeStrongBinder(rootNotification.mAllowlistToken);
- } else {
- parcel.writeStrongBinder(mAllowlistToken);
- }
+ // Always use the same token as the root notification (might be null).
+ IBinder rootNotificationToken = (IBinder) parcel.getClassCookie(Notification.class);
+ parcel.writeStrongBinder(rootNotificationToken);
} else {
parcel.writeStrongBinder(mAllowlistToken);
}
@@ -6597,12 +6593,7 @@
* @hide
*/
public RemoteViews createCompactHeadsUpContentView() {
- // TODO(b/336225281): re-evaluate custom view usage.
- if (useExistingRemoteView(mN.headsUpContentView)) {
- return fullyCustomViewRequiresDecoration(false /* fromStyle */)
- ? minimallyDecoratedHeadsUpContentView(mN.headsUpContentView)
- : mN.headsUpContentView;
- } else if (mStyle != null) {
+ if (mStyle != null) {
final RemoteViews styleView = mStyle.makeCompactHeadsUpContentView();
if (styleView != null) {
return styleView;
@@ -6615,7 +6606,7 @@
// Notification text is shown as secondary header text
// for the minimal hun when it is provided.
// Time(when and chronometer) is not shown for the minimal hun.
- p.headerTextSecondary(p.mText).text(null).hideTime(true);
+ p.headerTextSecondary(p.mText).text(null).hideTime(true).summaryText("");
return applyStandardTemplate(
getCompactHeadsUpBaseLayoutResource(), p,
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 8171723..9437c74 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -300,6 +300,16 @@
@EnabledSince(targetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM)
static final long ENABLE_CHECKING_TELEPHONY_FEATURES_FOR_VCN = 330902016;
+ /**
+ * The corresponding vendor API for Android V
+ *
+ * <p>Starting with Android V, the vendor API format has switched to YYYYMM.
+ *
+ * @see <a href="https://preview.source.android.com/docs/core/architecture/api-flags">Vendor API
+ * level</a>
+ */
+ private static final int VENDOR_API_FOR_ANDROID_V = 202404;
+
// Service registry information.
// This information is never changed once static initialization has completed.
private static final Map<Class<?>, String> SYSTEM_SERVICE_NAMES =
@@ -465,9 +475,10 @@
new CachedServiceFetcher<VcnManager>() {
@Override
public VcnManager createService(ContextImpl ctx) throws ServiceNotFoundException {
- if (shouldCheckTelephonyFeatures()
- && !ctx.getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)) {
+ final String telephonyFeatureToCheck = getVcnFeatureDependency();
+
+ if (telephonyFeatureToCheck != null
+ && !ctx.getPackageManager().hasSystemFeature(telephonyFeatureToCheck)) {
return null;
}
@@ -1768,16 +1779,24 @@
// partition SDK level, not application's target SDK version (which BTW we
// also check through Compatibility framework a few lines below).
@SuppressWarnings("AndroidFrameworkCompatChange")
- private static boolean shouldCheckTelephonyFeatures() {
+ @Nullable
+ private static String getVcnFeatureDependency() {
+ // Check SDK version of the client app. Apps targeting pre-V SDK might
+ // have not checked for existence of these features.
+ if (!Compatibility.isChangeEnabled(ENABLE_CHECKING_TELEPHONY_FEATURES_FOR_VCN)) {
+ return null;
+ }
+
// Check SDK version of the vendor partition. Pre-V devices might have
// incorrectly under-declared telephony features.
final int vendorApiLevel = SystemProperties.getInt(
"ro.vendor.api_level", Build.VERSION.DEVICE_INITIAL_SDK_INT);
- if (vendorApiLevel < Build.VERSION_CODES.VANILLA_ICE_CREAM) return false;
+ if (vendorApiLevel < VENDOR_API_FOR_ANDROID_V) {
+ return PackageManager.FEATURE_TELEPHONY;
+ } else {
+ return PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION;
+ }
- // Check SDK version of the client app. Apps targeting pre-V SDK might
- // have not checked for existence of these features.
- return Compatibility.isChangeEnabled(ENABLE_CHECKING_TELEPHONY_FEATURES_FOR_VCN);
}
/**
diff --git a/core/java/android/app/TaskStackListener.java b/core/java/android/app/TaskStackListener.java
index 0290cee..36f61fd 100644
--- a/core/java/android/app/TaskStackListener.java
+++ b/core/java/android/app/TaskStackListener.java
@@ -178,6 +178,9 @@
}
@Override
+ public void onTaskSnapshotInvalidated(int taskId) { }
+
+ @Override
public void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo)
throws RemoteException {
}
diff --git a/core/java/android/app/admin/DeviceAdminInfo.java b/core/java/android/app/admin/DeviceAdminInfo.java
index 9ef8b38..46c9e78 100644
--- a/core/java/android/app/admin/DeviceAdminInfo.java
+++ b/core/java/android/app/admin/DeviceAdminInfo.java
@@ -21,6 +21,7 @@
import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.app.admin.flags.Flags;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
@@ -176,6 +177,10 @@
* provisioned into "affiliated" mode when on a Headless System User Mode device.
*
* <p>This mode adds a Profile Owner to all users other than the user the Device Owner is on.
+ *
+ * <p>Starting from Android version {@link android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM},
+ * DPCs should set the value of attribute "headless-device-owner-mode" inside the
+ * "headless-system-user" tag as "affiliated".
*/
public static final int HEADLESS_DEVICE_OWNER_MODE_AFFILIATED = 1;
@@ -185,6 +190,10 @@
*
* <p>This mode only allows a single secondary user on the device blocking the creation of
* additional secondary users.
+ *
+ * <p>Starting from Android version {@link android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM},
+ * DPCs should set the value of attribute "headless-device-owner-mode" inside the
+ * "headless-system-user" tag as "single_user".
*/
@FlaggedApi(FLAG_HEADLESS_DEVICE_OWNER_SINGLE_USER_ENABLED)
public static final int HEADLESS_DEVICE_OWNER_MODE_SINGLE_USER = 2;
@@ -383,17 +392,30 @@
}
mSupportsTransferOwnership = true;
} else if (tagName.equals("headless-system-user")) {
- String deviceOwnerModeStringValue =
- parser.getAttributeValue(null, "device-owner-mode");
+ String deviceOwnerModeStringValue = null;
+ if (Flags.headlessSingleUserCompatibilityFix()) {
+ deviceOwnerModeStringValue = parser.getAttributeValue(
+ null, "headless-device-owner-mode");
+ }
+ if (deviceOwnerModeStringValue == null) {
+ deviceOwnerModeStringValue =
+ parser.getAttributeValue(null, "device-owner-mode");
+ }
- if (deviceOwnerModeStringValue.equalsIgnoreCase("unsupported")) {
+ if ("unsupported".equalsIgnoreCase(deviceOwnerModeStringValue)) {
mHeadlessDeviceOwnerMode = HEADLESS_DEVICE_OWNER_MODE_UNSUPPORTED;
- } else if (deviceOwnerModeStringValue.equalsIgnoreCase("affiliated")) {
+ } else if ("affiliated".equalsIgnoreCase(deviceOwnerModeStringValue)) {
mHeadlessDeviceOwnerMode = HEADLESS_DEVICE_OWNER_MODE_AFFILIATED;
- } else if (deviceOwnerModeStringValue.equalsIgnoreCase("single_user")) {
+ } else if ("single_user".equalsIgnoreCase(deviceOwnerModeStringValue)) {
mHeadlessDeviceOwnerMode = HEADLESS_DEVICE_OWNER_MODE_SINGLE_USER;
} else {
- throw new XmlPullParserException("headless-system-user mode must be valid");
+ if (Flags.headlessSingleUserCompatibilityFix()) {
+ Log.e(TAG, "Unknown headless-system-user mode: "
+ + deviceOwnerModeStringValue);
+ } else {
+ throw new XmlPullParserException(
+ "headless-system-user mode must be valid");
+ }
}
}
}
diff --git a/core/java/android/app/admin/StringSetPolicyValue.java b/core/java/android/app/admin/PackageSetPolicyValue.java
similarity index 71%
rename from core/java/android/app/admin/StringSetPolicyValue.java
rename to core/java/android/app/admin/PackageSetPolicyValue.java
index 12b11f4..8b253a2 100644
--- a/core/java/android/app/admin/StringSetPolicyValue.java
+++ b/core/java/android/app/admin/PackageSetPolicyValue.java
@@ -28,18 +28,18 @@
/**
* @hide
*/
-public final class StringSetPolicyValue extends PolicyValue<Set<String>> {
+public final class PackageSetPolicyValue extends PolicyValue<Set<String>> {
- public StringSetPolicyValue(@NonNull Set<String> value) {
+ public PackageSetPolicyValue(@NonNull Set<String> value) {
super(value);
if (Flags.devicePolicySizeTrackingInternalBugFixEnabled()) {
- for (String str : value) {
- PolicySizeVerifier.enforceMaxStringLength(str, "policyValue");
+ for (String packageName : value) {
+ PolicySizeVerifier.enforceMaxPackageNameLength(packageName);
}
}
}
- public StringSetPolicyValue(Parcel source) {
+ public PackageSetPolicyValue(Parcel source) {
this(readValues(source));
}
@@ -56,7 +56,7 @@
public boolean equals(@Nullable Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
- StringSetPolicyValue other = (StringSetPolicyValue) o;
+ PackageSetPolicyValue other = (PackageSetPolicyValue) o;
return Objects.equals(getValue(), other.getValue());
}
@@ -67,7 +67,7 @@
@Override
public String toString() {
- return "StringSetPolicyValue { " + getValue() + " }";
+ return "PackageNameSetPolicyValue { " + getValue() + " }";
}
@Override
@@ -84,16 +84,16 @@
}
@NonNull
- public static final Creator<StringSetPolicyValue> CREATOR =
- new Creator<StringSetPolicyValue>() {
+ public static final Creator<PackageSetPolicyValue> CREATOR =
+ new Creator<PackageSetPolicyValue>() {
@Override
- public StringSetPolicyValue createFromParcel(Parcel source) {
- return new StringSetPolicyValue(source);
+ public PackageSetPolicyValue createFromParcel(Parcel source) {
+ return new PackageSetPolicyValue(source);
}
@Override
- public StringSetPolicyValue[] newArray(int size) {
- return new StringSetPolicyValue[size];
+ public PackageSetPolicyValue[] newArray(int size) {
+ return new PackageSetPolicyValue[size];
}
};
}
diff --git a/core/java/android/app/admin/SystemUpdatePolicy.java b/core/java/android/app/admin/SystemUpdatePolicy.java
index 7320cea..dede5b5 100644
--- a/core/java/android/app/admin/SystemUpdatePolicy.java
+++ b/core/java/android/app/admin/SystemUpdatePolicy.java
@@ -78,6 +78,11 @@
*
* <h3>Developer guide</h3>
* To learn more, read <a href="{@docRoot}work/dpc/system-updates">Manage system updates</a>.
+ * <p><strong>Note:</strong> <a href="https://source.android.com/docs/core/ota/modular-system">
+ * Google Play system updates</a> (also called Mainline updates) are automatically downloaded
+ * but require a device reboot to be installed. Refer to the mainline section in
+ * <a href="{@docRoot}work/dpc/system-updates#mainline">Manage system
+ * updates</a> for further details.</p>
*
* @see DevicePolicyManager#setSystemUpdatePolicy
* @see DevicePolicyManager#getSystemUpdatePolicy
diff --git a/core/java/android/app/admin/flags/flags.aconfig b/core/java/android/app/admin/flags/flags.aconfig
index 18914e1..83daa45 100644
--- a/core/java/android/app/admin/flags/flags.aconfig
+++ b/core/java/android/app/admin/flags/flags.aconfig
@@ -303,3 +303,24 @@
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "headless_single_user_compatibility_fix"
+ namespace: "enterprise"
+ description: "Fix for compatibility issue introduced from using single_user mode on pre-Android V builds"
+ bug: "338050276"
+ is_exported: true
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
+ name: "headless_single_min_target_sdk"
+ namespace: "enterprise"
+ description: "Only allow DPCs targeting Android V to provision into single user mode"
+ bug: "338588825"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/core/java/android/app/notification.aconfig b/core/java/android/app/notification.aconfig
index e3c367f8..63ffaa0 100644
--- a/core/java/android/app/notification.aconfig
+++ b/core/java/android/app/notification.aconfig
@@ -39,6 +39,13 @@
}
flag {
+ name: "check_autogroup_before_post"
+ namespace: "systemui"
+ description: "Does a check to see if notification should be autogrouped before posting, and if so groups before post."
+ bug: "330214226"
+}
+
+flag {
name: "visit_risky_uris"
namespace: "systemui"
description: "Guards the security fix that ensures all URIs in intents and Person.java are valid"
diff --git a/core/java/android/app/trust/TrustManager.java b/core/java/android/app/trust/TrustManager.java
index e5f2976..23b2ea4 100644
--- a/core/java/android/app/trust/TrustManager.java
+++ b/core/java/android/app/trust/TrustManager.java
@@ -18,6 +18,7 @@
import android.Manifest;
import android.annotation.RequiresPermission;
+import android.annotation.SdkConstant;
import android.annotation.SystemService;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
@@ -40,6 +41,15 @@
@SystemService(Context.TRUST_SERVICE)
public class TrustManager {
+ /**
+ * Intent action used to identify services that can serve as significant providers.
+ *
+ * @hide
+ */
+ @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
+ public static final String ACTION_BIND_SIGNIFICANT_PLACE_PROVIDER =
+ "com.android.trust.provider.SignificantPlaceProvider.BIND";
+
private static final int MSG_TRUST_CHANGED = 1;
private static final int MSG_TRUST_MANAGED_CHANGED = 2;
private static final int MSG_TRUST_ERROR = 3;
diff --git a/core/java/android/appwidget/AppWidgetHost.java b/core/java/android/appwidget/AppWidgetHost.java
index 2dced96..72f992a 100644
--- a/core/java/android/appwidget/AppWidgetHost.java
+++ b/core/java/android/appwidget/AppWidgetHost.java
@@ -35,6 +35,7 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.DisplayMetrics;
+import android.util.Log;
import android.util.SparseArray;
import android.widget.RemoteViews;
import android.widget.RemoteViews.InteractionHandler;
@@ -52,12 +53,15 @@
*/
public class AppWidgetHost {
+ private static final String TAG = "AppWidgetHost";
+
static final int HANDLE_UPDATE = 1;
static final int HANDLE_PROVIDER_CHANGED = 2;
static final int HANDLE_PROVIDERS_CHANGED = 3;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
static final int HANDLE_VIEW_DATA_CHANGED = 4;
static final int HANDLE_APP_WIDGET_REMOVED = 5;
+ static final int HANDLE_VIEW_UPDATE_DEFERRED = 6;
final static Object sServiceLock = new Object();
@UnsupportedAppUsage
@@ -131,6 +135,15 @@
msg.sendToTarget();
}
+ public void updateAppWidgetDeferred(int appWidgetId) {
+ Handler handler = mWeakHandler.get();
+ if (handler == null) {
+ return;
+ }
+ Message msg = handler.obtainMessage(HANDLE_VIEW_UPDATE_DEFERRED, appWidgetId, 0, null);
+ msg.sendToTarget();
+ }
+
private static boolean isLocalBinder() {
return Process.myPid() == Binder.getCallingPid();
}
@@ -163,6 +176,10 @@
viewDataChanged(msg.arg1, msg.arg2);
break;
}
+ case HANDLE_VIEW_UPDATE_DEFERRED: {
+ updateAppWidgetDeferred(msg.arg1);
+ break;
+ }
}
}
}
@@ -480,14 +497,32 @@
void onUpdateProviderInfo(@Nullable AppWidgetProviderInfo appWidget);
/**
- * This function is called when the RemoteViews of the app widget is updated
- * @param views The new RemoteViews to be set for the app widget
+ * This function is called when the {@code RemoteViews} of the app widget is updated
+ * @param views The new {@code RemoteViews} to be set for the app widget
*
* @hide
*/
void updateAppWidget(@Nullable RemoteViews views);
/**
+ * Called for the listener to handle deferred {@code RemoteViews} updates. Default
+ * implementation is to update the widget directly.
+ * @param packageName The package name used for uid verification on the service side
+ * @param appWidgetId The widget id of the listener
+ *
+ * @hide
+ */
+ default void updateAppWidgetDeferred(String packageName, int appWidgetId) {
+ RemoteViews latestViews = null;
+ try {
+ latestViews = sService.getAppWidgetViews(packageName, appWidgetId);
+ } catch (Exception e) {
+ Log.e(TAG, "updateAppWidgetDeferred: ", e);
+ }
+ updateAppWidget(latestViews);
+ }
+
+ /**
* This function is called when the view ID is changed for the app widget
* @param viewId The new view ID to be be set for the widget
*
@@ -563,6 +598,15 @@
}
}
+ private void updateAppWidgetDeferred(int appWidgetId) {
+ AppWidgetHostListener v = getListener(appWidgetId);
+ if (v == null) {
+ Log.e(TAG, "updateAppWidgetDeferred: null listener for id: " + appWidgetId);
+ return;
+ }
+ v.updateAppWidgetDeferred(mContextOpPackageName, appWidgetId);
+ }
+
/**
* Clear the list of Views that have been created by this AppWidgetHost.
*/
diff --git a/core/java/android/content/AttributionSource.java b/core/java/android/content/AttributionSource.java
index af13011..b070742 100644
--- a/core/java/android/content/AttributionSource.java
+++ b/core/java/android/content/AttributionSource.java
@@ -753,6 +753,9 @@
@FlaggedApi(Flags.FLAG_SET_NEXT_ATTRIBUTION_SOURCE)
public @NonNull Builder setNextAttributionSource(@NonNull AttributionSource value) {
checkNotUsed();
+ if (value == null) {
+ throw new IllegalArgumentException("Null AttributionSource not permitted.");
+ }
mBuilderFieldsSet |= 0x20;
mAttributionSourceState.next =
new AttributionSourceState[]{value.mAttributionSourceState};
diff --git a/core/java/android/content/PermissionChecker.java b/core/java/android/content/PermissionChecker.java
index 0e3217d..cb8eb83 100644
--- a/core/java/android/content/PermissionChecker.java
+++ b/core/java/android/content/PermissionChecker.java
@@ -73,13 +73,12 @@
public static final int PERMISSION_GRANTED = PermissionCheckerManager.PERMISSION_GRANTED;
/**
- * The permission is denied. Applicable only to runtime and app op permissions.
+ * The permission is denied. Applicable only to runtime permissions.
*
* <p>Returned when:
* <ul>
* <li>the runtime permission is granted, but the corresponding app op is denied
* for runtime permissions.</li>
- * <li>the app ops is ignored for app op permissions.</li>
* </ul>
*
* @hide
diff --git a/core/java/android/content/pm/flags.aconfig b/core/java/android/content/pm/flags.aconfig
index 205f1e9..45591d7 100644
--- a/core/java/android/content/pm/flags.aconfig
+++ b/core/java/android/content/pm/flags.aconfig
@@ -248,3 +248,11 @@
bug: "316916801"
is_fixed_read_only: true
}
+
+flag {
+ name: "package_restart_query_disabled_by_default"
+ namespace: "package_manager_service"
+ description: "Feature flag to register broadcast receiver only support package restart query."
+ bug: "300309050"
+ is_fixed_read_only: true
+}
diff --git a/core/java/android/content/pm/multiuser.aconfig b/core/java/android/content/pm/multiuser.aconfig
index cd1913b..83742eb 100644
--- a/core/java/android/content/pm/multiuser.aconfig
+++ b/core/java/android/content/pm/multiuser.aconfig
@@ -240,3 +240,10 @@
description: "Add entrypoint in Settings Reset options for deleting private space when lock is forgotten"
bug: "329601751"
}
+
+flag {
+ name: "allow_main_user_to_access_blocked_number_provider"
+ namespace: "multiuser"
+ description: "Allow MAIN user to access blocked number provider"
+ bug: "338579331"
+}
diff --git a/core/java/android/content/res/AssetFileDescriptor.java b/core/java/android/content/res/AssetFileDescriptor.java
index 3486d5e..afddc77 100644
--- a/core/java/android/content/res/AssetFileDescriptor.java
+++ b/core/java/android/content/res/AssetFileDescriptor.java
@@ -419,6 +419,10 @@
if (available <= 0) {
return -1;
}
+ if (count == 0) {
+ // Java's InputStream explicitly specifies that this returns zero.
+ return 0;
+ }
if (count > available) count = available;
try {
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index a9f70c9..32d2a6f 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -308,8 +308,8 @@
*/
public static void getCameraInfo(int cameraId, CameraInfo cameraInfo) {
Context context = ActivityThread.currentApplication().getApplicationContext();
- boolean overrideToPortrait = CameraManager.shouldOverrideToPortrait(context);
- getCameraInfo(cameraId, context, overrideToPortrait, cameraInfo);
+ final int rotationOverride = CameraManager.getRotationOverride(context);
+ getCameraInfo(cameraId, context, rotationOverride, cameraInfo);
}
/**
@@ -320,8 +320,8 @@
@SuppressLint("UnflaggedApi") // @TestApi without associated feature.
@TestApi
public static void getCameraInfo(int cameraId, @NonNull Context context,
- boolean overrideToPortrait, CameraInfo cameraInfo) {
- _getCameraInfo(cameraId, overrideToPortrait, context.getDeviceId(),
+ int rotationOverride, CameraInfo cameraInfo) {
+ _getCameraInfo(cameraId, rotationOverride, context.getDeviceId(),
getDevicePolicyFromContext(context), cameraInfo);
IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);
IAudioService audioService = IAudioService.Stub.asInterface(b);
@@ -336,7 +336,7 @@
}
}
- private native static void _getCameraInfo(int cameraId, boolean overrideToPortrait,
+ private native static void _getCameraInfo(int cameraId, int rotationOverride,
int deviceId, int devicePolicy, CameraInfo cameraInfo);
private static int getDevicePolicyFromContext(Context context) {
@@ -441,8 +441,8 @@
*/
public static Camera open(int cameraId) {
Context context = ActivityThread.currentApplication().getApplicationContext();
- boolean overrideToPortrait = CameraManager.shouldOverrideToPortrait(context);
- return open(cameraId, context, overrideToPortrait);
+ final int rotationOverride = CameraManager.getRotationOverride(context);
+ return open(cameraId, context, rotationOverride);
}
/**
@@ -452,8 +452,8 @@
*/
@SuppressLint("UnflaggedApi") // @TestApi without associated feature.
@TestApi
- public static Camera open(int cameraId, @NonNull Context context, boolean overrideToPortrait) {
- return new Camera(cameraId, context, overrideToPortrait);
+ public static Camera open(int cameraId, @NonNull Context context, int rotationOverride) {
+ return new Camera(cameraId, context, rotationOverride);
}
/**
@@ -524,7 +524,7 @@
return open(cameraId);
}
- private int cameraInit(int cameraId, Context context, boolean overrideToPortrait) {
+ private int cameraInit(int cameraId, Context context, int rotationOverride) {
mShutterCallback = null;
mRawImageCallback = null;
mJpegCallback = null;
@@ -544,7 +544,7 @@
boolean forceSlowJpegMode = shouldForceSlowJpegMode();
return native_setup(new WeakReference<>(this), cameraId,
- ActivityThread.currentOpPackageName(), overrideToPortrait, forceSlowJpegMode,
+ ActivityThread.currentOpPackageName(), rotationOverride, forceSlowJpegMode,
context.getDeviceId(), getDevicePolicyFromContext(context));
}
@@ -562,9 +562,9 @@
}
/** used by Camera#open, Camera#open(int) */
- Camera(int cameraId, @NonNull Context context, boolean overrideToPortrait) {
+ Camera(int cameraId, @NonNull Context context, int rotationOverride) {
Objects.requireNonNull(context);
- int err = cameraInit(cameraId, context, overrideToPortrait);
+ final int err = cameraInit(cameraId, context, rotationOverride);
if (checkInitErrors(err)) {
if (err == -EACCES) {
throw new RuntimeException("Fail to connect to camera service");
@@ -629,7 +629,7 @@
@UnsupportedAppUsage
private native int native_setup(Object cameraThis, int cameraId, String packageName,
- boolean overrideToPortrait, boolean forceSlowJpegMode, int deviceId, int devicePolicy);
+ int rotationOverride, boolean forceSlowJpegMode, int deviceId, int devicePolicy);
private native final void native_release();
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index 90a2cf0..a019612 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -28,6 +28,8 @@
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
+import android.app.ActivityManager;
+import android.app.TaskInfo;
import android.app.compat.CompatChanges;
import android.companion.virtual.VirtualDeviceManager;
import android.compat.annotation.ChangeId;
@@ -67,6 +69,7 @@
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
+import android.util.Pair;
import android.util.Size;
import android.view.Display;
@@ -169,6 +172,36 @@
"camera.enable_landscape_to_portrait";
/**
+ * Does not override landscape feed to portrait.
+ *
+ * @hide
+ */
+ @TestApi
+ @FlaggedApi(com.android.window.flags.Flags.FLAG_CAMERA_COMPAT_FOR_FREEFORM)
+ public static final int ROTATION_OVERRIDE_NONE = ICameraService.ROTATION_OVERRIDE_NONE;
+
+ /**
+ * Crops and rotates landscape camera feed to portrait, and changes sensor orientation to
+ * portrait.
+ *
+ * @hide
+ */
+ @TestApi
+ @FlaggedApi(com.android.window.flags.Flags.FLAG_CAMERA_COMPAT_FOR_FREEFORM)
+ public static final int ROTATION_OVERRIDE_OVERRIDE_TO_PORTRAIT =
+ ICameraService.ROTATION_OVERRIDE_OVERRIDE_TO_PORTRAIT;
+
+ /**
+ * Crops and rotates landscape camera feed to portrait, but doesn't change sensor orientation.
+ *
+ * @hide
+ */
+ @TestApi
+ @FlaggedApi(com.android.window.flags.Flags.FLAG_CAMERA_COMPAT_FOR_FREEFORM)
+ public static final int ROTATION_OVERRIDE_ROTATION_ONLY =
+ ICameraService.ROTATION_OVERRIDE_ROTATION_ONLY;
+
+ /**
* Enable physical camera availability callbacks when the logical camera is unavailable
*
* <p>Previously once a logical camera becomes unavailable, no
@@ -347,7 +380,8 @@
*/
@NonNull
public Set<Set<String>> getConcurrentCameraIds() throws CameraAccessException {
- return CameraManagerGlobal.get().getConcurrentCameraIds();
+ return CameraManagerGlobal.get().getConcurrentCameraIds(mContext.getDeviceId(),
+ getDevicePolicyFromContext(mContext));
}
/**
@@ -386,7 +420,8 @@
@NonNull Map<String, SessionConfiguration> cameraIdAndSessionConfig)
throws CameraAccessException {
return CameraManagerGlobal.get().isConcurrentSessionConfigurationSupported(
- cameraIdAndSessionConfig, mContext.getApplicationInfo().targetSdkVersion);
+ cameraIdAndSessionConfig, mContext.getApplicationInfo().targetSdkVersion,
+ mContext.getDeviceId(), getDevicePolicyFromContext(mContext));
}
/**
@@ -627,7 +662,8 @@
CameraMetadataNative physicalCameraInfo =
cameraService.getCameraCharacteristics(physicalCameraId,
mContext.getApplicationInfo().targetSdkVersion,
- /*overrideToPortrait*/ false, DEVICE_ID_DEFAULT,
+ /*rotationOverride*/ ICameraService.ROTATION_OVERRIDE_NONE,
+ DEVICE_ID_DEFAULT,
DEVICE_POLICY_DEFAULT);
StreamConfiguration[] configs = physicalCameraInfo.get(
CameraCharacteristics.
@@ -674,7 +710,7 @@
@NonNull
public CameraCharacteristics getCameraCharacteristics(@NonNull String cameraId)
throws CameraAccessException {
- return getCameraCharacteristics(cameraId, shouldOverrideToPortrait(mContext));
+ return getCameraCharacteristics(cameraId, getRotationOverride(mContext));
}
/**
@@ -699,7 +735,16 @@
@NonNull
public CameraCharacteristics getCameraCharacteristics(@NonNull String cameraId,
boolean overrideToPortrait) throws CameraAccessException {
- CameraCharacteristics characteristics;
+ return getCameraCharacteristics(cameraId,
+ overrideToPortrait
+ ? ICameraService.ROTATION_OVERRIDE_OVERRIDE_TO_PORTRAIT
+ : ICameraService.ROTATION_OVERRIDE_NONE);
+ }
+
+ @NonNull
+ private CameraCharacteristics getCameraCharacteristics(@NonNull String cameraId,
+ int rotationOverride) throws CameraAccessException {
+ CameraCharacteristics characteristics = null;
if (CameraManagerGlobal.sCameraServiceDisabled) {
throw new IllegalArgumentException("No cameras available on device");
}
@@ -711,7 +756,7 @@
}
try {
CameraMetadataNative info = cameraService.getCameraCharacteristics(cameraId,
- mContext.getApplicationInfo().targetSdkVersion, overrideToPortrait,
+ mContext.getApplicationInfo().targetSdkVersion, rotationOverride,
mContext.getDeviceId(), getDevicePolicyFromContext(mContext));
characteristics = prepareCameraCharacteristics(cameraId, info, cameraService);
} catch (ServiceSpecificException e) {
@@ -752,7 +797,7 @@
boolean hasConcurrentStreams =
CameraManagerGlobal.get().cameraIdHasConcurrentStreamsLocked(cameraId,
- mContext.getDeviceId());
+ mContext.getDeviceId(), getDevicePolicyFromContext(mContext));
metadata.setHasMandatoryConcurrentStreams(hasConcurrentStreams);
Size displaySize = getDisplaySize();
@@ -926,7 +971,7 @@
*/
private CameraDevice openCameraDeviceUserAsync(String cameraId,
CameraDevice.StateCallback callback, Executor executor, final int uid,
- final int oomScoreOffset, boolean overrideToPortrait) throws CameraAccessException {
+ final int oomScoreOffset, int rotationOverride) throws CameraAccessException {
CameraCharacteristics characteristics = getCameraCharacteristics(cameraId);
CameraDevice device = null;
Map<String, CameraCharacteristics> physicalIdsToChars =
@@ -961,7 +1006,7 @@
cameraUser = cameraService.connectDevice(callbacks, cameraId,
mContext.getOpPackageName(), mContext.getAttributionTag(), uid,
oomScoreOffset, mContext.getApplicationInfo().targetSdkVersion,
- overrideToPortrait, mContext.getDeviceId(),
+ rotationOverride, mContext.getDeviceId(),
getDevicePolicyFromContext(mContext));
} catch (ServiceSpecificException e) {
if (e.errorCode == ICameraService.ERROR_DEPRECATED_HAL) {
@@ -1126,7 +1171,10 @@
@Nullable Handler handler,
@NonNull final CameraDevice.StateCallback callback) throws CameraAccessException {
openCameraForUid(cameraId, callback, CameraDeviceImpl.checkAndWrapHandler(handler),
- USE_CALLING_UID, /*oomScoreOffset*/0, overrideToPortrait);
+ USE_CALLING_UID, /*oomScoreOffset*/0,
+ overrideToPortrait
+ ? ICameraService.ROTATION_OVERRIDE_OVERRIDE_TO_PORTRAIT
+ : ICameraService.ROTATION_OVERRIDE_NONE);
}
/**
@@ -1240,7 +1288,7 @@
"oomScoreOffset < 0, cannot increase priority of camera client");
}
openCameraForUid(cameraId, callback, executor, USE_CALLING_UID, oomScoreOffset,
- shouldOverrideToPortrait(mContext));
+ getRotationOverride(mContext));
}
/**
@@ -1258,11 +1306,14 @@
* Must be USE_CALLING_UID unless the caller is a trusted service.
* @param oomScoreOffset
* The minimum oom score that cameraservice must see for this client.
+ * @param rotationOverride
+ * The type of rotation override (none, override_to_portrait, rotation_only)
+ * that should be followed for this camera id connection
* @hide
*/
public void openCameraForUid(@NonNull String cameraId,
@NonNull final CameraDevice.StateCallback callback, @NonNull Executor executor,
- int clientUid, int oomScoreOffset, boolean overrideToPortrait)
+ int clientUid, int oomScoreOffset, int rotationOverride)
throws CameraAccessException {
if (cameraId == null) {
@@ -1275,7 +1326,7 @@
}
openCameraDeviceUserAsync(cameraId, callback, executor, clientUid, oomScoreOffset,
- overrideToPortrait);
+ rotationOverride);
}
/**
@@ -1297,7 +1348,7 @@
@NonNull final CameraDevice.StateCallback callback, @NonNull Executor executor,
int clientUid) throws CameraAccessException {
openCameraForUid(cameraId, callback, executor, clientUid, /*oomScoreOffset*/0,
- shouldOverrideToPortrait(mContext));
+ getRotationOverride(mContext));
}
/**
@@ -1442,7 +1493,7 @@
/**
* @hide
*/
- public static boolean shouldOverrideToPortrait(@Nullable Context context) {
+ public static int getRotationOverride(@Nullable Context context) {
PackageManager packageManager = null;
String packageName = null;
@@ -1451,7 +1502,64 @@
packageName = context.getOpPackageName();
}
- return shouldOverrideToPortrait(packageManager, packageName);
+ return getRotationOverride(context, packageManager, packageName);
+ }
+
+ /**
+ * @hide
+ */
+ public static int getRotationOverride(@Nullable Context context,
+ @Nullable PackageManager packageManager, @Nullable String packageName) {
+ if (com.android.window.flags.Flags.cameraCompatForFreeform()) {
+ return getRotationOverrideInternal(context, packageManager, packageName);
+ } else {
+ return shouldOverrideToPortrait(packageManager, packageName)
+ ? ICameraService.ROTATION_OVERRIDE_OVERRIDE_TO_PORTRAIT
+ : ICameraService.ROTATION_OVERRIDE_NONE;
+ }
+ }
+
+ /**
+ * @hide
+ */
+ @FlaggedApi(com.android.window.flags.Flags.FLAG_CAMERA_COMPAT_FOR_FREEFORM)
+ @TestApi
+ public static int getRotationOverrideInternal(@Nullable Context context,
+ @Nullable PackageManager packageManager, @Nullable String packageName) {
+ if (!CameraManagerGlobal.sLandscapeToPortrait) {
+ return ICameraService.ROTATION_OVERRIDE_NONE;
+ }
+
+ if (context != null) {
+ final ActivityManager activityManager =
+ context.getSystemService(ActivityManager.class);
+ for (ActivityManager.AppTask appTask : activityManager.getAppTasks()) {
+ final TaskInfo taskInfo = appTask.getTaskInfo();
+ if (taskInfo.appCompatTaskInfo.cameraCompatTaskInfo.freeformCameraCompatMode
+ != 0
+ && taskInfo.topActivity != null
+ && taskInfo.topActivity.getPackageName().equals(packageName)) {
+ // WindowManager has requested rotation override.
+ return ICameraService.ROTATION_OVERRIDE_ROTATION_ONLY;
+ }
+ }
+ }
+
+ if (packageManager != null && packageName != null) {
+ try {
+ return packageManager.getProperty(
+ PackageManager.PROPERTY_COMPAT_OVERRIDE_LANDSCAPE_TO_PORTRAIT,
+ packageName).getBoolean()
+ ? ICameraService.ROTATION_OVERRIDE_OVERRIDE_TO_PORTRAIT
+ : ICameraService.ROTATION_OVERRIDE_NONE;
+ } catch (PackageManager.NameNotFoundException e) {
+ // No such property
+ }
+ }
+
+ return CompatChanges.isChangeEnabled(OVERRIDE_CAMERA_LANDSCAPE_TO_PORTRAIT)
+ ? ICameraService.ROTATION_OVERRIDE_OVERRIDE_TO_PORTRAIT
+ : ICameraService.ROTATION_OVERRIDE_NONE;
}
/**
@@ -1459,7 +1567,7 @@
*/
@TestApi
public static boolean shouldOverrideToPortrait(@Nullable PackageManager packageManager,
- @Nullable String packageName) {
+ @Nullable String packageName) {
if (!CameraManagerGlobal.sLandscapeToPortrait) {
return false;
}
@@ -1477,6 +1585,7 @@
return CompatChanges.isChangeEnabled(OVERRIDE_CAMERA_LANDSCAPE_TO_PORTRAIT);
}
+
/**
* @hide
*/
@@ -1991,7 +2100,7 @@
// Opened Camera ID -> apk name map
private final ArrayMap<DeviceCameraInfo, String> mOpenedDevices = new ArrayMap<>();
- private final Set<Set<String>> mConcurrentCameraIdCombinations = new ArraySet<>();
+ private final Set<Set<DeviceCameraInfo>> mConcurrentCameraIdCombinations = new ArraySet<>();
// Registered availability callbacks and their executors
private final ArrayMap<AvailabilityCallback, Executor> mCallbackMap = new ArrayMap<>();
@@ -2150,7 +2259,13 @@
ConcurrentCameraIdCombination[] cameraIdCombinations =
cameraService.getConcurrentCameraIds();
for (ConcurrentCameraIdCombination comb : cameraIdCombinations) {
- mConcurrentCameraIdCombinations.add(comb.getConcurrentCameraIdCombination());
+ Set<Pair<String, Integer>> combination =
+ comb.getConcurrentCameraIdCombination();
+ Set<DeviceCameraInfo> deviceCameraInfoSet = new ArraySet<>();
+ for (Pair<String, Integer> entry : combination) {
+ deviceCameraInfoSet.add(new DeviceCameraInfo(entry.first, entry.second));
+ }
+ mConcurrentCameraIdCombinations.add(deviceCameraInfoSet);
}
} catch (ServiceSpecificException e) {
// Unexpected failure
@@ -2235,13 +2350,12 @@
return cameraIds.toArray(new String[0]);
}
- private Set<Set<String>> extractConcurrentCameraIdListLocked() {
+ private Set<Set<String>> extractConcurrentCameraIdListLocked(int deviceId,
+ int devicePolicy) {
Set<Set<String>> concurrentCameraIds = new ArraySet<>();
- for (Set<String> cameraIds : mConcurrentCameraIdCombinations) {
+ for (Set<DeviceCameraInfo> deviceCameraInfos : mConcurrentCameraIdCombinations) {
Set<String> extractedCameraIds = new ArraySet<>();
- for (String cameraId : cameraIds) {
- // TODO(b/291736219): This to be made device-aware.
- DeviceCameraInfo info = new DeviceCameraInfo(cameraId, DEVICE_ID_DEFAULT);
+ for (DeviceCameraInfo info : deviceCameraInfos) {
// if the camera id status is NOT_PRESENT or ENUMERATING; skip the device.
// TODO: Would a device status NOT_PRESENT ever be in the map ? it gets removed
// in the callback anyway.
@@ -2254,9 +2368,14 @@
|| status == ICameraServiceListener.STATUS_NOT_PRESENT) {
continue;
}
- extractedCameraIds.add(cameraId);
+ if (shouldHideCamera(deviceId, devicePolicy, info)) {
+ continue;
+ }
+ extractedCameraIds.add(info.mCameraId);
}
- concurrentCameraIds.add(extractedCameraIds);
+ if (!extractedCameraIds.isEmpty()) {
+ concurrentCameraIds.add(extractedCameraIds);
+ }
}
return concurrentCameraIds;
}
@@ -2417,12 +2536,13 @@
return cameraIds;
}
- public @NonNull Set<Set<String>> getConcurrentCameraIds() {
+ public @NonNull Set<Set<String>> getConcurrentCameraIds(int deviceId, int devicePolicy) {
Set<Set<String>> concurrentStreamingCameraIds;
synchronized (mLock) {
// Try to make sure we have an up-to-date list of concurrent camera devices.
connectCameraServiceLocked();
- concurrentStreamingCameraIds = extractConcurrentCameraIdListLocked();
+ concurrentStreamingCameraIds = extractConcurrentCameraIdListLocked(deviceId,
+ devicePolicy);
}
// TODO: Some sort of sorting ?
return concurrentStreamingCameraIds;
@@ -2430,13 +2550,12 @@
public boolean isConcurrentSessionConfigurationSupported(
@NonNull Map<String, SessionConfiguration> cameraIdsAndSessionConfigurations,
- int targetSdkVersion) throws CameraAccessException {
+ int targetSdkVersion, int deviceId, int devicePolicy)
+ throws CameraAccessException {
if (cameraIdsAndSessionConfigurations == null) {
throw new IllegalArgumentException("cameraIdsAndSessionConfigurations was null");
}
- // TODO(b/291736219): Check if this API needs to be made device-aware.
-
int size = cameraIdsAndSessionConfigurations.size();
if (size == 0) {
throw new IllegalArgumentException("camera id and session combination is empty");
@@ -2446,14 +2565,20 @@
// Go through all the elements and check if the camera ids are valid at least /
// belong to one of the combinations returned by getConcurrentCameraIds()
boolean subsetFound = false;
- for (Set<String> combination : mConcurrentCameraIdCombinations) {
- if (combination.containsAll(cameraIdsAndSessionConfigurations.keySet())) {
+ for (Set<DeviceCameraInfo> combination : mConcurrentCameraIdCombinations) {
+ Set<DeviceCameraInfo> infos = new ArraySet<>();
+ for (String cameraId : cameraIdsAndSessionConfigurations.keySet()) {
+ infos.add(new DeviceCameraInfo(cameraId,
+ devicePolicy == DEVICE_POLICY_DEFAULT
+ ? DEVICE_ID_DEFAULT : deviceId));
+ }
+ if (combination.containsAll(infos)) {
subsetFound = true;
}
}
if (!subsetFound) {
Log.v(TAG, "isConcurrentSessionConfigurationSupported called with a subset of"
- + "camera ids not returned by getConcurrentCameraIds");
+ + " camera ids not returned by getConcurrentCameraIds");
return false;
}
CameraIdAndSessionConfiguration [] cameraIdsAndConfigs =
@@ -2467,7 +2592,7 @@
}
try {
return mCameraService.isConcurrentSessionConfigurationSupported(
- cameraIdsAndConfigs, targetSdkVersion);
+ cameraIdsAndConfigs, targetSdkVersion, deviceId, devicePolicy);
} catch (ServiceSpecificException e) {
throw ExceptionUtils.throwAsPublicException(e);
} catch (RemoteException e) {
@@ -2486,8 +2611,10 @@
* @return Whether the camera device was found in the set of combinations returned by
* getConcurrentCameraIds
*/
- public boolean cameraIdHasConcurrentStreamsLocked(String cameraId, int deviceId) {
- DeviceCameraInfo info = new DeviceCameraInfo(cameraId, deviceId);
+ public boolean cameraIdHasConcurrentStreamsLocked(String cameraId, int deviceId,
+ int devicePolicy) {
+ DeviceCameraInfo info = new DeviceCameraInfo(cameraId,
+ devicePolicy == DEVICE_POLICY_DEFAULT ? DEVICE_ID_DEFAULT : deviceId);
if (!mDeviceStatus.containsKey(info)) {
// physical camera ids aren't advertised in concurrent camera id combinations.
if (DEBUG) {
@@ -2496,8 +2623,8 @@
}
return false;
}
- for (Set<String> comb : mConcurrentCameraIdCombinations) {
- if (comb.contains(cameraId)) {
+ for (Set<DeviceCameraInfo> comb : mConcurrentCameraIdCombinations) {
+ if (comb.contains(info)) {
return true;
}
}
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceSetupImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceSetupImpl.java
index 372839d..8898a4c 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceSetupImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceSetupImpl.java
@@ -134,7 +134,8 @@
try {
CameraMetadataNative metadata = cameraService.getSessionCharacteristics(
mCameraId, mTargetSdkVersion,
- CameraManager.shouldOverrideToPortrait(mContext), sessionConfig,
+ CameraManager.getRotationOverride(mContext),
+ sessionConfig,
mContext.getDeviceId(),
mCameraManager.getDevicePolicyFromContext(mContext));
diff --git a/core/java/android/hardware/camera2/utils/ConcurrentCameraIdCombination.java b/core/java/android/hardware/camera2/utils/ConcurrentCameraIdCombination.java
index 8f4d636..1a8bf1d 100644
--- a/core/java/android/hardware/camera2/utils/ConcurrentCameraIdCombination.java
+++ b/core/java/android/hardware/camera2/utils/ConcurrentCameraIdCombination.java
@@ -13,13 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package android.hardware.camera2.utils;
import android.annotation.NonNull;
import android.os.Parcel;
import android.os.Parcelable;
+import android.util.ArraySet;
+import android.util.Pair;
-import java.util.HashSet;
import java.util.Set;
/**
@@ -30,21 +32,21 @@
*/
public class ConcurrentCameraIdCombination implements Parcelable {
- private Set<String> mConcurrentCameraIds = new HashSet<>();
+ private final Set<Pair<String, Integer>> mConcurrentCameraIdDeviceIdPairs = new ArraySet<>();
public static final @NonNull
Parcelable.Creator<ConcurrentCameraIdCombination> CREATOR =
- new Parcelable.Creator<ConcurrentCameraIdCombination>() {
- @Override
- public ConcurrentCameraIdCombination createFromParcel(Parcel in) {
- return new ConcurrentCameraIdCombination(in);
- }
+ new Parcelable.Creator<>() {
+ @Override
+ public ConcurrentCameraIdCombination createFromParcel(Parcel in) {
+ return new ConcurrentCameraIdCombination(in);
+ }
- @Override
- public ConcurrentCameraIdCombination[] newArray(int size) {
- return new ConcurrentCameraIdCombination[size];
- }
- };
+ @Override
+ public ConcurrentCameraIdCombination[] newArray(int size) {
+ return new ConcurrentCameraIdCombination[size];
+ }
+ };
private ConcurrentCameraIdCombination(Parcel in) {
readFromParcel(in);
@@ -57,9 +59,10 @@
@Override
public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mConcurrentCameraIds.size());
- for (String cameraId : mConcurrentCameraIds) {
- dest.writeString(cameraId);
+ dest.writeInt(mConcurrentCameraIdDeviceIdPairs.size());
+ for (Pair<String, Integer> cameraIdDeviceIdPair : mConcurrentCameraIdDeviceIdPairs) {
+ dest.writeString(cameraIdDeviceIdPair.first);
+ dest.writeInt(cameraIdDeviceIdPair.second);
}
}
@@ -67,7 +70,7 @@
* helper for CREATOR
*/
public void readFromParcel(Parcel in) {
- mConcurrentCameraIds.clear();
+ mConcurrentCameraIdDeviceIdPairs.clear();
int cameraCombinationSize = in.readInt();
if (cameraCombinationSize < 0) {
throw new RuntimeException("cameraCombinationSize " + cameraCombinationSize
@@ -78,14 +81,15 @@
if (cameraId == null) {
throw new RuntimeException("Failed to read camera id from Parcel");
}
- mConcurrentCameraIds.add(cameraId);
+ int deviceId = in.readInt();
+ mConcurrentCameraIdDeviceIdPairs.add(new Pair<>(cameraId, deviceId));
}
}
/**
* Get this concurrent camera id combination.
*/
- public Set<String> getConcurrentCameraIdCombination() {
- return mConcurrentCameraIds;
+ public Set<Pair<String, Integer>> getConcurrentCameraIdCombination() {
+ return mConcurrentCameraIdDeviceIdPairs;
}
}
diff --git a/core/java/android/hardware/hdmi/OWNERS b/core/java/android/hardware/hdmi/OWNERS
index 6952e5d..f7a22f5 100644
--- a/core/java/android/hardware/hdmi/OWNERS
+++ b/core/java/android/hardware/hdmi/OWNERS
@@ -3,3 +3,4 @@
include /services/core/java/com/android/server/display/OWNERS
quxiangfang@google.com
+donpaul@google.com
\ No newline at end of file
diff --git a/core/java/android/hardware/lights/Light.java b/core/java/android/hardware/lights/Light.java
index 18d0b09..163f9fa 100644
--- a/core/java/android/hardware/lights/Light.java
+++ b/core/java/android/hardware/lights/Light.java
@@ -65,6 +65,12 @@
public static final int LIGHT_TYPE_KEYBOARD_BACKLIGHT = 10003;
/**
+ * Type for keyboard microphone mute light.
+ * @hide
+ */
+ public static final int LIGHT_TYPE_KEYBOARD_MIC_MUTE = 10004;
+
+ /**
* Capability for lights that could adjust its LED brightness. If the capability is not present
* the LED can only be turned either on or off.
*/
@@ -92,6 +98,7 @@
LIGHT_TYPE_INPUT,
LIGHT_TYPE_PLAYER_ID,
LIGHT_TYPE_KEYBOARD_BACKLIGHT,
+ LIGHT_TYPE_KEYBOARD_MIC_MUTE,
})
public @interface LightType {}
diff --git a/core/java/android/hardware/location/ISignificantPlaceProvider.aidl b/core/java/android/hardware/location/ISignificantPlaceProvider.aidl
new file mode 100644
index 0000000..e02169e
--- /dev/null
+++ b/core/java/android/hardware/location/ISignificantPlaceProvider.aidl
@@ -0,0 +1,10 @@
+package android.hardware.location;
+
+import android.hardware.location.ISignificantPlaceProviderManager;
+
+/**
+ * @hide
+ */
+oneway interface ISignificantPlaceProvider {
+ void setSignificantPlaceProviderManager(in ISignificantPlaceProviderManager manager);
+}
diff --git a/core/java/android/hardware/location/ISignificantPlaceProviderManager.aidl b/core/java/android/hardware/location/ISignificantPlaceProviderManager.aidl
new file mode 100644
index 0000000..76eefe7
--- /dev/null
+++ b/core/java/android/hardware/location/ISignificantPlaceProviderManager.aidl
@@ -0,0 +1,8 @@
+package android.hardware.location;
+
+/**
+ * @hide
+ */
+interface ISignificantPlaceProviderManager {
+ void setInSignificantPlace(in boolean inSignificantPlace);
+}
diff --git a/core/java/android/net/vcn/flags.aconfig b/core/java/android/net/vcn/flags.aconfig
index fea2c25..d4d1ed2 100644
--- a/core/java/android/net/vcn/flags.aconfig
+++ b/core/java/android/net/vcn/flags.aconfig
@@ -38,6 +38,16 @@
}
flag{
+ name: "enforce_main_user"
+ namespace: "vcn"
+ description: "Enforce main user to make VCN HSUM compatible"
+ bug: "310310661"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag{
name: "handle_seq_num_leap"
namespace: "vcn"
description: "Do not report bad network when there is a suspected sequence number leap"
@@ -45,4 +55,14 @@
metadata {
purpose: PURPOSE_BUGFIX
}
+}
+
+flag{
+ name: "allow_disable_ipsec_loss_detector"
+ namespace: "vcn"
+ description: "Allow disabling IPsec packet loss detector"
+ bug: "336638836"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
}
\ No newline at end of file
diff --git a/core/java/android/os/IHintManager.aidl b/core/java/android/os/IHintManager.aidl
index e057a85..360b2ac 100644
--- a/core/java/android/os/IHintManager.aidl
+++ b/core/java/android/os/IHintManager.aidl
@@ -18,6 +18,7 @@
package android.os;
import android.os.IHintSession;
+import android.hardware.power.ChannelConfig;
import android.hardware.power.SessionConfig;
import android.hardware.power.SessionTag;
@@ -27,6 +28,9 @@
* Creates a {@link Session} for the given set of threads and associates to a binder token.
* Returns a config if creation is not supported, and HMS had to use the
* legacy creation method.
+ *
+ * Throws UnsupportedOperationException if ADPF is not supported, and IllegalStateException
+ * if creation is supported but fails.
*/
IHintSession createHintSessionWithConfig(in IBinder token, in int[] threadIds,
in long durationNanos, in SessionTag tag, out @nullable SessionConfig config);
@@ -38,4 +42,12 @@
void setHintSessionThreads(in IHintSession hintSession, in int[] tids);
int[] getHintSessionThreadIds(in IHintSession hintSession);
+
+ /**
+ * Returns FMQ channel information for the caller, which it associates to a binder token.
+ *
+ * Throws IllegalStateException if FMQ channel creation fails.
+ */
+ ChannelConfig getSessionChannel(in IBinder token);
+ oneway void closeSessionChannel();
}
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index d38354d..c6a9203 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -1989,85 +1989,86 @@
* @hide
*/
@StringDef(value = {
- DISALLOW_MODIFY_ACCOUNTS,
- DISALLOW_CONFIG_WIFI,
- DISALLOW_CONFIG_LOCALE,
- DISALLOW_INSTALL_APPS,
- DISALLOW_UNINSTALL_APPS,
- DISALLOW_SHARE_LOCATION,
+ ALLOW_PARENT_PROFILE_APP_LINKING,
+ DISALLOW_ADD_CLONE_PROFILE,
+ DISALLOW_ADD_MANAGED_PROFILE,
+ DISALLOW_ADD_PRIVATE_PROFILE,
+ DISALLOW_ADD_USER,
+ DISALLOW_ADD_WIFI_CONFIG,
+ DISALLOW_ADJUST_VOLUME,
DISALLOW_AIRPLANE_MODE,
- DISALLOW_CONFIG_BRIGHTNESS,
DISALLOW_AMBIENT_DISPLAY,
- DISALLOW_CONFIG_SCREEN_TIMEOUT,
- DISALLOW_INSTALL_UNKNOWN_SOURCES,
- DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY,
- DISALLOW_CONFIG_BLUETOOTH,
+ DISALLOW_APPS_CONTROL,
+ DISALLOW_ASSIST_CONTENT,
+ DISALLOW_AUTOFILL,
+ DISALLOW_BIOMETRIC,
DISALLOW_BLUETOOTH,
DISALLOW_BLUETOOTH_SHARING,
- DISALLOW_USB_FILE_TRANSFER,
- DISALLOW_CONFIG_CREDENTIALS,
- DISALLOW_REMOVE_USER,
- DISALLOW_REMOVE_MANAGED_PROFILE,
- DISALLOW_DEBUGGING_FEATURES,
- DISALLOW_CONFIG_VPN,
- DISALLOW_CONFIG_LOCATION,
- DISALLOW_CONFIG_DATE_TIME,
- DISALLOW_CONFIG_TETHERING,
- DISALLOW_NETWORK_RESET,
- DISALLOW_FACTORY_RESET,
- DISALLOW_ADD_USER,
- DISALLOW_ADD_MANAGED_PROFILE,
- DISALLOW_ADD_CLONE_PROFILE,
- DISALLOW_ADD_PRIVATE_PROFILE,
- ENSURE_VERIFY_APPS,
- DISALLOW_CONFIG_CELL_BROADCASTS,
- DISALLOW_CONFIG_MOBILE_NETWORKS,
- DISALLOW_APPS_CONTROL,
- DISALLOW_MOUNT_PHYSICAL_MEDIA,
- DISALLOW_UNMUTE_MICROPHONE,
- DISALLOW_ADJUST_VOLUME,
- DISALLOW_OUTGOING_CALLS,
- DISALLOW_SMS,
- DISALLOW_FUN,
- DISALLOW_CREATE_WINDOWS,
- DISALLOW_SYSTEM_ERROR_DIALOGS,
- DISALLOW_CROSS_PROFILE_COPY_PASTE,
- DISALLOW_OUTGOING_BEAM,
- DISALLOW_WALLPAPER,
- DISALLOW_SET_WALLPAPER,
- DISALLOW_SAFE_BOOT,
- DISALLOW_RECORD_AUDIO,
- DISALLOW_RUN_IN_BACKGROUND,
DISALLOW_CAMERA,
- DISALLOW_UNMUTE_DEVICE,
- DISALLOW_DATA_ROAMING,
- DISALLOW_SET_USER_ICON,
- DISALLOW_OEM_UNLOCK,
- DISALLOW_UNIFIED_PASSWORD,
- ALLOW_PARENT_PROFILE_APP_LINKING,
- DISALLOW_AUTOFILL,
+ DISALLOW_CAMERA_TOGGLE,
+ DISALLOW_CELLULAR_2G,
+ DISALLOW_CHANGE_WIFI_STATE,
+ DISALLOW_CONFIG_BLUETOOTH,
+ DISALLOW_CONFIG_BRIGHTNESS,
+ DISALLOW_CONFIG_CELL_BROADCASTS,
+ DISALLOW_CONFIG_CREDENTIALS,
+ DISALLOW_CONFIG_DATE_TIME,
+ DISALLOW_CONFIG_DEFAULT_APPS,
+ DISALLOW_CONFIG_LOCALE,
+ DISALLOW_CONFIG_LOCATION,
+ DISALLOW_CONFIG_MOBILE_NETWORKS,
+ DISALLOW_CONFIG_PRIVATE_DNS,
+ DISALLOW_CONFIG_SCREEN_TIMEOUT,
+ DISALLOW_CONFIG_TETHERING,
+ DISALLOW_CONFIG_VPN,
+ DISALLOW_CONFIG_WIFI,
DISALLOW_CONTENT_CAPTURE,
DISALLOW_CONTENT_SUGGESTIONS,
- DISALLOW_USER_SWITCH,
- DISALLOW_SHARE_INTO_MANAGED_PROFILE,
- DISALLOW_PRINTING,
- DISALLOW_CONFIG_PRIVATE_DNS,
- DISALLOW_MICROPHONE_TOGGLE,
- DISALLOW_CAMERA_TOGGLE,
- KEY_RESTRICTIONS_PENDING,
- DISALLOW_BIOMETRIC,
- DISALLOW_CHANGE_WIFI_STATE,
- DISALLOW_WIFI_TETHERING,
- DISALLOW_SHARING_ADMIN_CONFIGURED_WIFI,
- DISALLOW_WIFI_DIRECT,
- DISALLOW_ADD_WIFI_CONFIG,
- DISALLOW_CELLULAR_2G,
- DISALLOW_ULTRA_WIDEBAND_RADIO,
+ DISALLOW_CREATE_WINDOWS,
+ DISALLOW_CROSS_PROFILE_COPY_PASTE,
+ DISALLOW_DATA_ROAMING,
+ DISALLOW_DEBUGGING_FEATURES,
+ DISALLOW_FACTORY_RESET,
+ DISALLOW_FUN,
DISALLOW_GRANT_ADMIN,
+ DISALLOW_INSTALL_APPS,
+ DISALLOW_INSTALL_UNKNOWN_SOURCES,
+ DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY,
+ DISALLOW_MICROPHONE_TOGGLE,
+ DISALLOW_MODIFY_ACCOUNTS,
+ DISALLOW_MOUNT_PHYSICAL_MEDIA,
DISALLOW_NEAR_FIELD_COMMUNICATION_RADIO,
- DISALLOW_THREAD_NETWORK,
+ DISALLOW_NETWORK_RESET,
+ DISALLOW_OEM_UNLOCK,
+ DISALLOW_OUTGOING_BEAM,
+ DISALLOW_OUTGOING_CALLS,
+ DISALLOW_PRINTING,
+ DISALLOW_RECORD_AUDIO,
+ DISALLOW_REMOVE_MANAGED_PROFILE,
+ DISALLOW_REMOVE_USER,
+ DISALLOW_RUN_IN_BACKGROUND,
+ DISALLOW_SAFE_BOOT,
+ DISALLOW_SET_USER_ICON,
+ DISALLOW_SET_WALLPAPER,
+ DISALLOW_SHARE_INTO_MANAGED_PROFILE,
+ DISALLOW_SHARE_LOCATION,
+ DISALLOW_SHARING_ADMIN_CONFIGURED_WIFI,
DISALLOW_SIM_GLOBALLY,
- DISALLOW_ASSIST_CONTENT,
+ DISALLOW_SMS,
+ DISALLOW_SYSTEM_ERROR_DIALOGS,
+ DISALLOW_THREAD_NETWORK,
+ DISALLOW_ULTRA_WIDEBAND_RADIO,
+ DISALLOW_UNIFIED_PASSWORD,
+ DISALLOW_UNINSTALL_APPS,
+ DISALLOW_UNMUTE_DEVICE,
+ DISALLOW_UNMUTE_MICROPHONE,
+ DISALLOW_USB_FILE_TRANSFER,
+ DISALLOW_USER_SWITCH,
+ DISALLOW_WALLPAPER,
+ DISALLOW_WIFI_DIRECT,
+ DISALLOW_WIFI_TETHERING,
+ ENSURE_VERIFY_APPS,
+ KEY_RESTRICTIONS_PENDING,
})
@Retention(RetentionPolicy.SOURCE)
public @interface UserRestrictionKey {}
diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java
index 55bb430..7e51cb0 100644
--- a/core/java/android/permission/PermissionManager.java
+++ b/core/java/android/permission/PermissionManager.java
@@ -112,7 +112,7 @@
public static final int PERMISSION_GRANTED = 0;
/**
- * The permission is denied. Applicable only to runtime and app op permissions.
+ * The permission is denied. Applicable only to runtime permissions.
* <p>
* The app isn't expecting the permission to be denied so that a "no-op" action should be taken,
* such as returning an empty result.
diff --git a/core/java/android/tracing/flags.aconfig b/core/java/android/tracing/flags.aconfig
index 74428aa..d7389ba 100644
--- a/core/java/android/tracing/flags.aconfig
+++ b/core/java/android/tracing/flags.aconfig
@@ -30,3 +30,11 @@
is_fixed_read_only: true
bug: "276433199"
}
+
+flag {
+ name: "perfetto_view_capture_tracing"
+ namespace: "windowing_tools"
+ description: "Migrate ViewCapture tracing to Perfetto"
+ is_fixed_read_only: true
+ bug: "323166383"
+}
diff --git a/core/java/android/tracing/inputmethod/InputMethodDataSource.java b/core/java/android/tracing/inputmethod/InputMethodDataSource.java
new file mode 100644
index 0000000..5c5ad69
--- /dev/null
+++ b/core/java/android/tracing/inputmethod/InputMethodDataSource.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.tracing.inputmethod;
+
+import android.annotation.NonNull;
+import android.tracing.perfetto.DataSource;
+import android.tracing.perfetto.DataSourceInstance;
+import android.tracing.perfetto.StartCallbackArguments;
+import android.tracing.perfetto.StopCallbackArguments;
+import android.util.proto.ProtoInputStream;
+
+/**
+ * @hide
+ */
+public final class InputMethodDataSource
+ extends DataSource<DataSourceInstance, Void, Void> {
+ public static final String DATA_SOURCE_NAME = "android.inputmethod";
+
+ @NonNull
+ private final Runnable mOnStartCallback;
+ @NonNull
+ private final Runnable mOnStopCallback;
+
+ public InputMethodDataSource(@NonNull Runnable onStart, @NonNull Runnable onStop) {
+ super(DATA_SOURCE_NAME);
+ mOnStartCallback = onStart;
+ mOnStopCallback = onStop;
+ }
+
+ @Override
+ public DataSourceInstance createInstance(ProtoInputStream configStream, int instanceIndex) {
+ return new DataSourceInstance(this, instanceIndex) {
+ @Override
+ protected void onStart(StartCallbackArguments args) {
+ mOnStartCallback.run();
+ }
+
+ @Override
+ protected void onStop(StopCallbackArguments args) {
+ mOnStopCallback.run();
+ }
+ };
+ }
+}
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 65d9b3a..cb5a885 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -62,7 +62,6 @@
import android.view.InputDevice;
import android.view.IInputFilter;
import android.view.AppTransitionAnimationSpec;
-import android.view.TaskTransitionSpec;
import android.view.WindowContentFrameStats;
import android.view.WindowManager;
import android.view.SurfaceControl;
@@ -962,19 +961,6 @@
void setTaskSnapshotEnabled(boolean enabled);
/**
- * Customized the task transition animation with a task transition spec.
- *
- * @param spec the spec that will be used to customize the task animations
- */
- void setTaskTransitionSpec(in TaskTransitionSpec spec);
-
- /**
- * Clears any task transition spec that has been previously set and
- * reverts to using the default task transition with no spec changes.
- */
- void clearTaskTransitionSpec();
-
- /**
* Registers the frame rate per second count callback for one given task ID.
* Each callback can only register for receiving FPS callback for one task id until unregister
* is called. If there's no task associated with the given task id,
diff --git a/core/java/android/view/ImeBackAnimationController.java b/core/java/android/view/ImeBackAnimationController.java
index 1afedc1..9503f49 100644
--- a/core/java/android/view/ImeBackAnimationController.java
+++ b/core/java/android/view/ImeBackAnimationController.java
@@ -38,6 +38,8 @@
import com.android.internal.inputmethod.SoftInputShowHideReason;
+import java.io.PrintWriter;
+
/**
* Controller for IME predictive back animation
*
@@ -134,7 +136,9 @@
@Override
public void onBackInvoked() {
- if (!isBackAnimationAllowed()) {
+ if (!isBackAnimationAllowed() || !mIsPreCommitAnimationInProgress) {
+ // play regular hide animation if back-animation is not allowed or if insets control has
+ // been cancelled by the system (this can happen in split screen for example)
mInsetsController.hide(ime());
return;
}
@@ -269,4 +273,24 @@
return mPostCommitAnimator != null && mTriggerBack;
}
+ /**
+ * Dump information about this ImeBackAnimationController
+ *
+ * @param prefix the prefix that will be prepended to each line of the produced output
+ * @param writer the writer that will receive the resulting text
+ */
+ public void dump(String prefix, PrintWriter writer) {
+ final String innerPrefix = prefix + " ";
+ writer.println(prefix + "ImeBackAnimationController:");
+ writer.println(innerPrefix + "mLastProgress=" + mLastProgress);
+ writer.println(innerPrefix + "mTriggerBack=" + mTriggerBack);
+ writer.println(innerPrefix + "mIsPreCommitAnimationInProgress="
+ + mIsPreCommitAnimationInProgress);
+ writer.println(innerPrefix + "mStartRootScrollY=" + mStartRootScrollY);
+ writer.println(innerPrefix + "isBackAnimationAllowed=" + isBackAnimationAllowed());
+ writer.println(innerPrefix + "isAdjustPan=" + isAdjustPan());
+ writer.println(innerPrefix + "isHideAnimationInProgress="
+ + isHideAnimationInProgress());
+ }
+
}
diff --git a/core/java/android/view/InputWindowHandle.java b/core/java/android/view/InputWindowHandle.java
index de5fc7f..58ef5ef 100644
--- a/core/java/android/view/InputWindowHandle.java
+++ b/core/java/android/view/InputWindowHandle.java
@@ -67,7 +67,7 @@
InputConfig.SPY,
InputConfig.INTERCEPTS_STYLUS,
InputConfig.CLONE,
- InputConfig.SENSITIVE_FOR_TRACING,
+ InputConfig.SENSITIVE_FOR_PRIVACY,
})
public @interface InputConfigFlags {}
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index c545267..f1cb410 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -1799,8 +1799,11 @@
}
void dump(String prefix, PrintWriter pw) {
- pw.print(prefix); pw.println("InsetsController:");
- mState.dump(prefix + " ", pw);
+ final String innerPrefix = prefix + " ";
+ pw.println(prefix + "InsetsController:");
+ mState.dump(innerPrefix, pw);
+ pw.println(innerPrefix + "mIsPredictiveBackImeHideAnimInProgress="
+ + mIsPredictiveBackImeHideAnimInProgress);
}
void dumpDebug(ProtoOutputStream proto, long fieldId) {
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 1ee9509..154f1fe 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -25,6 +25,7 @@
import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
+import android.os.IInputConstants;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.method.MetaKeyKeyListener;
@@ -1295,7 +1296,7 @@
* action for a key until it receives an up or the long press timeout has
* expired.
*/
- public static final int FLAG_CANCELED = 0x20;
+ public static final int FLAG_CANCELED = IInputConstants.INPUT_EVENT_FLAG_CANCELED;
/**
* This key event was generated by a virtual (on-screen) hard key area.
@@ -1363,7 +1364,7 @@
* @see #isTainted
* @see #setTainted
*/
- public static final int FLAG_TAINTED = 0x80000000;
+ public static final int FLAG_TAINTED = IInputConstants.INPUT_EVENT_FLAG_TAINTED;
/**
* Returns the maximum keycode.
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 56a24e4..38f9a91 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -16,7 +16,15 @@
package android.view;
+import static android.os.IInputConstants.INPUT_EVENT_FLAG_CANCELED;
+import static android.os.IInputConstants.MOTION_EVENT_FLAG_HOVER_EXIT_PENDING;
import static android.os.IInputConstants.INPUT_EVENT_FLAG_IS_ACCESSIBILITY_EVENT;
+import static android.os.IInputConstants.MOTION_EVENT_FLAG_IS_GENERATED_GESTURE;
+import static android.os.IInputConstants.MOTION_EVENT_FLAG_NO_FOCUS_CHANGE;
+import static android.os.IInputConstants.INPUT_EVENT_FLAG_TAINTED;
+import static android.os.IInputConstants.MOTION_EVENT_FLAG_TARGET_ACCESSIBILITY_FOCUS;
+import static android.os.IInputConstants.MOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
+import static android.os.IInputConstants.MOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
import static android.view.Display.DEFAULT_DISPLAY;
import static java.lang.annotation.RetentionPolicy.SOURCE;
@@ -448,7 +456,7 @@
* to drop the suspect touches or to take additional precautions to confirm the user's
* actual intent.
*/
- public static final int FLAG_WINDOW_IS_OBSCURED = 0x1;
+ public static final int FLAG_WINDOW_IS_OBSCURED = MOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
/**
* This flag indicates that the window that received this motion event is partly
@@ -464,7 +472,8 @@
* Unlike FLAG_WINDOW_IS_OBSCURED, this is only true if the window that received this event is
* obstructed in areas other than the touched location.
*/
- public static final int FLAG_WINDOW_IS_PARTIALLY_OBSCURED = 0x2;
+ public static final int FLAG_WINDOW_IS_PARTIALLY_OBSCURED =
+ MOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
/**
* This private flag is only set on {@link #ACTION_HOVER_MOVE} events and indicates that
@@ -472,7 +481,7 @@
* prevent generating redundant {@link #ACTION_HOVER_ENTER} events.
* @hide
*/
- public static final int FLAG_HOVER_EXIT_PENDING = 0x4;
+ public static final int FLAG_HOVER_EXIT_PENDING = MOTION_EVENT_FLAG_HOVER_EXIT_PENDING;
/**
* This flag indicates that the event has been generated by a gesture generator. It
@@ -480,7 +489,7 @@
*
* @hide
*/
- public static final int FLAG_IS_GENERATED_GESTURE = 0x8;
+ public static final int FLAG_IS_GENERATED_GESTURE = MOTION_EVENT_FLAG_IS_GENERATED_GESTURE;
/**
* This flag is only set for events with {@link #ACTION_POINTER_UP} and {@link #ACTION_CANCEL}.
@@ -493,7 +502,7 @@
* @see #ACTION_POINTER_UP
* @see #ACTION_CANCEL
*/
- public static final int FLAG_CANCELED = 0x20;
+ public static final int FLAG_CANCELED = INPUT_EVENT_FLAG_CANCELED;
/**
* This flag indicates that the event will not cause a focus change if it is directed to an
@@ -502,7 +511,7 @@
* window into focus.
* @hide
*/
- public static final int FLAG_NO_FOCUS_CHANGE = 0x40;
+ public static final int FLAG_NO_FOCUS_CHANGE = MOTION_EVENT_FLAG_NO_FOCUS_CHANGE;
/**
* This flag indicates that this event was modified by or generated from an accessibility
@@ -521,7 +530,7 @@
* @see #isTainted
* @see #setTainted
*/
- public static final int FLAG_TAINTED = 0x80000000;
+ public static final int FLAG_TAINTED = INPUT_EVENT_FLAG_TAINTED;
/**
* Private flag indicating that this event was synthesized by the system and should be delivered
@@ -536,7 +545,8 @@
* @see #isTargetAccessibilityFocus()
* @see #setTargetAccessibilityFocus(boolean)
*/
- public static final int FLAG_TARGET_ACCESSIBILITY_FOCUS = 0x40000000;
+ public static final int FLAG_TARGET_ACCESSIBILITY_FOCUS =
+ MOTION_EVENT_FLAG_TARGET_ACCESSIBILITY_FOCUS;
/**
* Flag indicating the motion event intersected the top edge of the screen.
diff --git a/core/java/android/view/PointerIcon.java b/core/java/android/view/PointerIcon.java
index 7dc151d..71199e9 100644
--- a/core/java/android/view/PointerIcon.java
+++ b/core/java/android/view/PointerIcon.java
@@ -234,7 +234,7 @@
}
int typeIndex = getSystemIconTypeIndex(type);
- if (typeIndex == 0) {
+ if (typeIndex < 0) {
typeIndex = getSystemIconTypeIndex(TYPE_DEFAULT);
}
@@ -606,7 +606,7 @@
case TYPE_HANDWRITING:
return com.android.internal.R.styleable.Pointer_pointerIconHandwriting;
default:
- return 0;
+ return -1;
}
}
diff --git a/core/java/android/view/TaskTransitionSpec.aidl b/core/java/android/view/TaskTransitionSpec.aidl
deleted file mode 100644
index 08af15c..0000000
--- a/core/java/android/view/TaskTransitionSpec.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
-** Copyright 2021, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.view;
-
-/** @hide */
-parcelable TaskTransitionSpec;
diff --git a/core/java/android/view/TaskTransitionSpec.java b/core/java/android/view/TaskTransitionSpec.java
deleted file mode 100644
index 9a2d3ba..0000000
--- a/core/java/android/view/TaskTransitionSpec.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * Holds information about how to execute task transition animations.
- *
- * This class is intended to be used with IWindowManager.setTaskTransitionSpec methods when
- * we want more customization over the way default task transitions are executed.
- *
- * @hide
- */
-public class TaskTransitionSpec implements Parcelable {
- /**
- * The background color to use during task animations (override the default background color)
- */
- public final int backgroundColor;
-
- public TaskTransitionSpec(int backgroundColor) {
- this.backgroundColor = backgroundColor;
- }
-
- public TaskTransitionSpec(Parcel in) {
- this.backgroundColor = in.readInt();
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(backgroundColor);
- }
-
- public static final @android.annotation.NonNull Parcelable.Creator<TaskTransitionSpec>
- CREATOR = new Parcelable.Creator<TaskTransitionSpec>() {
- public TaskTransitionSpec createFromParcel(Parcel in) {
- return new TaskTransitionSpec(in);
- }
-
- public TaskTransitionSpec[] newArray(int size) {
- return new TaskTransitionSpec[size];
- }
- };
-}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index a844370..60ad926 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -5773,7 +5773,7 @@
*/
private static final float FRAME_RATE_SIZE_PERCENTAGE_THRESHOLD = 0.07f;
- static final float MAX_FRAME_RATE = 140;
+ static final float MAX_FRAME_RATE = 120;
// The preferred frame rate of the view that is mainly used for
// touch boosting, view velocity handling, and TextureView.
@@ -32229,7 +32229,7 @@
void increaseSensitiveViewsCount() {
if (mSensitiveViewsCount == 0) {
- mViewRootImpl.notifySensitiveContentAppProtection(true);
+ mViewRootImpl.addSensitiveContentAppProtection();
}
mSensitiveViewsCount++;
}
@@ -32237,7 +32237,7 @@
void decreaseSensitiveViewsCount() {
mSensitiveViewsCount--;
if (mSensitiveViewsCount == 0) {
- mViewRootImpl.notifySensitiveContentAppProtection(false);
+ mViewRootImpl.removeSensitiveContentAppProtection();
}
if (mSensitiveViewsCount < 0) {
Log.wtf(VIEW_LOG_TAG, "mSensitiveViewsCount is negative" + mSensitiveViewsCount);
@@ -33944,8 +33944,9 @@
protected int calculateFrameRateCategory() {
int category;
switch (getViewRootImpl().intermittentUpdateState()) {
- case ViewRootImpl.INTERMITTENT_STATE_INTERMITTENT ->
- category = FRAME_RATE_CATEGORY_NORMAL | FRAME_RATE_CATEGORY_REASON_INTERMITTENT;
+ case ViewRootImpl.INTERMITTENT_STATE_INTERMITTENT -> category =
+ (sToolkitFrameRateBySizeReadOnlyFlagValue ? FRAME_RATE_CATEGORY_LOW
+ : FRAME_RATE_CATEGORY_NORMAL) | FRAME_RATE_CATEGORY_REASON_INTERMITTENT;
case ViewRootImpl.INTERMITTENT_STATE_NOT_INTERMITTENT ->
category = mSizeBasedFrameRateCategoryAndReason;
default -> category = mLastFrameRateCategory;
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 11ad86c..ab529e6 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -2654,9 +2654,10 @@
ViewRootImpl viewRootImpl = getViewRootImpl();
if (actionMasked == MotionEvent.ACTION_DOWN || mFirstTouchTarget != null) {
final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
- final boolean isDispatchingBack = (viewRootImpl != null
- && viewRootImpl.getOnBackInvokedDispatcher().isDispatching());
- if (!disallowIntercept || isDispatchingBack) { // Allow back to intercept touch
+ final boolean isBackGestureInProgress = (viewRootImpl != null
+ && viewRootImpl.getOnBackInvokedDispatcher().isBackGestureInProgress());
+ if (!disallowIntercept || isBackGestureInProgress) {
+ // Allow back to intercept touch
intercepted = onInterceptTouchEvent(ev);
ev.setAction(action); // restore action in case it was changed
} else {
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index f51d909..fdf3cb1 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -25,6 +25,7 @@
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.DragEvent.ACTION_DRAG_LOCATION;
+import static android.view.flags.Flags.sensitiveContentPrematureProtectionRemovedFix;
import static android.view.InputDevice.SOURCE_CLASS_NONE;
import static android.view.InsetsSource.ID_IME;
import static android.view.Surface.FRAME_RATE_CATEGORY_DEFAULT;
@@ -317,6 +318,7 @@
private static final boolean DEBUG_SCROLL_CAPTURE = false || LOCAL_LOGV;
private static final boolean DEBUG_TOUCH_NAVIGATION = false || LOCAL_LOGV;
private static final boolean DEBUG_BLAST = false || LOCAL_LOGV;
+ private static final boolean DEBUG_SENSITIVE_CONTENT = false || LOCAL_LOGV;
private static final int LOGTAG_INPUT_FOCUS = 62001;
private static final int LOGTAG_VIEWROOT_DRAW_EVENT = 60004;
@@ -4243,7 +4245,14 @@
mReportNextDraw = false;
mLastReportNextDrawReason = null;
mActiveSurfaceSyncGroup = null;
- mHasPendingTransactions = false;
+ if (mHasPendingTransactions) {
+ // TODO: We shouldn't ever actually hit this, it means mPendingTransaction wasn't
+ // merged with a sync group or BLASTBufferQueue before making it to this point
+ // But better a one or two frame flicker than steady-state broken from dropping
+ // whatever is in this transaction
+ mPendingTransaction.apply();
+ mHasPendingTransactions = false;
+ }
mSyncBuffer = false;
if (isInWMSRequestedSync()) {
mWmsRequestSyncGroup.markSyncReady();
@@ -4261,7 +4270,9 @@
updateInfrequentCount();
setPreferredFrameRate(mPreferredFrameRate);
setPreferredFrameRateCategory(mPreferredFrameRateCategory);
- if (!mIsFrameRateConflicted) {
+ if (mPreferredFrameRate > 0
+ || (mLastPreferredFrameRate != 0 && mPreferredFrameRate == 0)
+ ) {
mHandler.removeMessages(MSG_FRAME_RATE_SETTING);
mHandler.sendEmptyMessageDelayed(MSG_FRAME_RATE_SETTING,
FRAME_RATE_SETTING_REEVALUATE_TIME);
@@ -4328,20 +4339,55 @@
* <li>It should only notify service to unblock projection when all sensitive view are
* removed from the window.
* </ol>
+ *
+ * @param enableProtection if true, the protection is enabled for this window.
+ * if false, the protection is removed for this window.
*/
- void notifySensitiveContentAppProtection(boolean showSensitiveContent) {
+ private void applySensitiveContentAppProtection(boolean enableProtection) {
try {
if (mSensitiveContentProtectionService == null) {
return;
}
+ if (DEBUG_SENSITIVE_CONTENT) {
+ Log.d(TAG, "Notify sensitive content, package=" + mContext.getPackageName()
+ + ", token=" + getWindowToken() + ", flag=" + enableProtection);
+ }
// The window would be blocked during screen share if it shows sensitive content.
mSensitiveContentProtectionService.setSensitiveContentProtection(
- getWindowToken(), mContext.getPackageName(), showSensitiveContent);
+ getWindowToken(), mContext.getPackageName(), enableProtection);
} catch (RemoteException ex) {
Log.e(TAG, "Unable to protect sensitive content during screen share", ex);
}
}
+ /**
+ * Add sensitive content protection, when there are one or more visible sensitive views.
+ */
+ void addSensitiveContentAppProtection() {
+ applySensitiveContentAppProtection(true);
+ }
+
+ /**
+ * Remove sensitive content protection, when there is no visible sensitive view.
+ */
+ void removeSensitiveContentAppProtection() {
+ if (!sensitiveContentPrematureProtectionRemovedFix()) {
+ applySensitiveContentAppProtection(false);
+ return;
+ }
+ if (DEBUG_SENSITIVE_CONTENT) {
+ Log.d(TAG, "Add transaction to remove sensitive content protection, package="
+ + mContext.getPackageName() + ", token=" + getWindowToken());
+ }
+ Transaction t = new Transaction();
+ t.addTransactionCommittedListener(mExecutor, () -> {
+ if (mAttachInfo.mSensitiveViewsCount == 0) {
+ applySensitiveContentAppProtection(false);
+ }
+ });
+ applyTransactionOnDraw(t);
+ }
+
private void notifyContentCaptureEvents() {
if (!isContentCaptureEnabled()) {
if (DEBUG_CONTENT_CAPTURE) {
@@ -5254,10 +5300,12 @@
if (DEBUG_CONTENT_CAPTURE) {
Log.v(mTag, "performContentCaptureInitialReport() on " + rootView);
}
+ boolean traceDispatchCapture = false;
try {
if (!isContentCaptureEnabled()) return;
- if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
+ traceDispatchCapture = Trace.isTagEnabled(Trace.TRACE_TAG_VIEW);
+ if (traceDispatchCapture) {
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "dispatchContentCapture() for "
+ getClass().getSimpleName());
}
@@ -5273,7 +5321,9 @@
// Content capture is a go!
rootView.dispatchInitialProvideContentCaptureStructure();
} finally {
- Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+ if (traceDispatchCapture) {
+ Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+ }
}
}
@@ -5281,10 +5331,12 @@
if (DEBUG_CONTENT_CAPTURE) {
Log.v(mTag, "handleContentCaptureFlush()");
}
+ boolean traceFlushContentCapture = false;
try {
if (!isContentCaptureEnabled()) return;
- if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
+ traceFlushContentCapture = Trace.isTagEnabled(Trace.TRACE_TAG_VIEW);
+ if (traceFlushContentCapture) {
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "flushContentCapture for "
+ getClass().getSimpleName());
}
@@ -5296,7 +5348,9 @@
}
ccm.flush(ContentCaptureSession.FLUSH_REASON_VIEW_ROOT_ENTERED);
} finally {
- Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+ if (traceFlushContentCapture) {
+ Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+ }
}
}
@@ -7228,7 +7282,7 @@
private int doOnBackKeyEvent(KeyEvent keyEvent) {
WindowOnBackInvokedDispatcher dispatcher = getOnBackInvokedDispatcher();
OnBackInvokedCallback topCallback = dispatcher.getTopCallback();
- if (dispatcher.isDispatching()) {
+ if (dispatcher.isBackGestureInProgress()) {
return FINISH_NOT_HANDLED;
}
if (topCallback instanceof OnBackAnimationCallback) {
@@ -7746,6 +7800,7 @@
mWindowAttributes.type)) {
// set the frame rate to the maximum value.
mIsTouchBoosting = true;
+ setPreferredFrameRateCategory(mLastPreferredFrameRateCategory);
}
/**
* We want to lower the refresh rate when MotionEvent.ACTION_UP,
@@ -9554,6 +9609,8 @@
mOnBackInvokedDispatcher.dump(prefix, writer);
+ mImeBackAnimationController.dump(prefix, writer);
+
writer.println(prefix + "View Hierarchy:");
dumpViewHierarchy(innerPrefix, writer, mView);
}
@@ -12610,10 +12667,12 @@
view = mFrameRateCategoryView;
}
+ boolean traceFrameRateCategory = false;
try {
if (frameRateCategory != FRAME_RATE_CATEGORY_DEFAULT
&& mLastPreferredFrameRateCategory != frameRateCategory) {
- if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
+ traceFrameRateCategory = Trace.isTagEnabled(Trace.TRACE_TAG_VIEW);
+ if (traceFrameRateCategory) {
String reason = reasonToString(frameRateReason);
String sourceView = view == null ? "-" : view;
String category = categoryToString(frameRateCategory);
@@ -12631,7 +12690,9 @@
} catch (Exception e) {
Log.e(mTag, "Unable to set frame rate category", e);
} finally {
- Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+ if (traceFrameRateCategory) {
+ Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+ }
}
}
@@ -12671,9 +12732,11 @@
return;
}
+ boolean traceFrameRate = false;
try {
if (mLastPreferredFrameRate != preferredFrameRate) {
- if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
+ traceFrameRate = Trace.isTagEnabled(Trace.TRACE_TAG_VIEW);
+ if (traceFrameRate) {
Trace.traceBegin(
Trace.TRACE_TAG_VIEW, "ViewRootImpl#setFrameRate "
+ preferredFrameRate + " compatibility "
@@ -12688,7 +12751,9 @@
} catch (Exception e) {
Log.e(mTag, "Unable to set frame rate", e);
} finally {
- Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+ if (traceFrameRate) {
+ Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+ }
}
}
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 0bc2430..f22e8f5 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -4365,7 +4365,8 @@
public static final int INPUT_FEATURE_SPY = 1 << 2;
/**
- * Input feature used to indicate that this window is sensitive for tracing.
+ * Input feature used to indicate that this window is privacy sensitive. This may be used
+ * to redact input interactions from tracing or screen mirroring.
* <p>
* A window that uses {@link LayoutParams#FLAG_SECURE} will automatically be treated as
* a sensitive for input tracing, but this input feature can be set on windows that don't
@@ -4378,7 +4379,7 @@
*
* @hide
*/
- public static final int INPUT_FEATURE_SENSITIVE_FOR_TRACING = 1 << 3;
+ public static final int INPUT_FEATURE_SENSITIVE_FOR_PRIVACY = 1 << 3;
/**
* An internal annotation for flags that can be specified to {@link #inputFeatures}.
@@ -4392,7 +4393,7 @@
INPUT_FEATURE_NO_INPUT_CHANNEL,
INPUT_FEATURE_DISABLE_USER_ACTIVITY,
INPUT_FEATURE_SPY,
- INPUT_FEATURE_SENSITIVE_FOR_TRACING,
+ INPUT_FEATURE_SENSITIVE_FOR_PRIVACY,
})
public @interface InputFeatureFlags {
}
diff --git a/core/java/android/view/animation/AnimationSet.java b/core/java/android/view/animation/AnimationSet.java
index a2f3544..5aaa994 100644
--- a/core/java/android/view/animation/AnimationSet.java
+++ b/core/java/android/view/animation/AnimationSet.java
@@ -374,7 +374,7 @@
final Animation a = mAnimations.get(i);
temp.clear();
- a.getTransformationAt(interpolatedTime, t);
+ a.getTransformationAt(interpolatedTime, temp);
t.compose(temp);
}
}
diff --git a/core/java/android/view/animation/Transformation.java b/core/java/android/view/animation/Transformation.java
index de31667..812ecd1 100644
--- a/core/java/android/view/animation/Transformation.java
+++ b/core/java/android/view/animation/Transformation.java
@@ -78,6 +78,7 @@
mHasClipRect = false;
mAlpha = 1.0f;
mTransformationType = TYPE_BOTH;
+ mInsets = Insets.NONE;
}
/**
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index c7df15c..bfe4e6f 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -1592,7 +1592,8 @@
// request comes in but PCC Detection hasn't been triggered. There is no benefit to
// trigger PCC Detection separately in those cases.
if (!isActiveLocked()) {
- final boolean clientAdded = tryAddServiceClientIfNeededLocked();
+ final boolean clientAdded =
+ tryAddServiceClientIfNeededLocked(isCredmanRequested);
if (clientAdded) {
startSessionLocked(/* id= */ AutofillId.NO_AUTOFILL_ID, /* bounds= */ null,
/* value= */ null, /* flags= */ FLAG_PCC_DETECTION);
@@ -1850,7 +1851,8 @@
Rect bounds, AutofillValue value, int flags) {
if (shouldIgnoreViewEnteredLocked(id, flags)) return null;
- final boolean clientAdded = tryAddServiceClientIfNeededLocked();
+ boolean credmanRequested = isCredmanRequested(view);
+ final boolean clientAdded = tryAddServiceClientIfNeededLocked(credmanRequested);
if (!clientAdded) {
if (sVerbose) Log.v(TAG, "ignoring notifyViewEntered(" + id + "): no service client");
return null;
@@ -2645,6 +2647,11 @@
*/
@GuardedBy("mLock")
private boolean tryAddServiceClientIfNeededLocked() {
+ return tryAddServiceClientIfNeededLocked(/*credmanRequested=*/ false);
+ }
+
+ @GuardedBy("mLock")
+ private boolean tryAddServiceClientIfNeededLocked(boolean credmanRequested) {
final AutofillClient client = getClient();
if (client == null) {
return false;
@@ -2659,7 +2666,7 @@
final int userId = mContext.getUserId();
final SyncResultReceiver receiver = new SyncResultReceiver(SYNC_CALLS_TIMEOUT_MS);
mService.addClient(mServiceClient, client.autofillClientGetComponentName(),
- userId, receiver);
+ userId, receiver, credmanRequested);
int flags = 0;
try {
flags = receiver.getIntResult();
diff --git a/core/java/android/view/autofill/IAutoFillManager.aidl b/core/java/android/view/autofill/IAutoFillManager.aidl
index cefd6dc..1a9322e 100644
--- a/core/java/android/view/autofill/IAutoFillManager.aidl
+++ b/core/java/android/view/autofill/IAutoFillManager.aidl
@@ -38,7 +38,7 @@
oneway interface IAutoFillManager {
// Returns flags: FLAG_ADD_CLIENT_ENABLED | FLAG_ADD_CLIENT_DEBUG | FLAG_ADD_CLIENT_VERBOSE
void addClient(in IAutoFillManagerClient client, in ComponentName componentName, int userId,
- in IResultReceiver result);
+ in IResultReceiver result, boolean credmanRequested);
void removeClient(in IAutoFillManagerClient client, int userId);
void startSession(IBinder activityToken, in IBinder appCallback, in AutofillId autoFillId,
in Rect bounds, in AutofillValue value, int userId, boolean hasCallback, int flags,
diff --git a/core/java/android/view/flags/view_flags.aconfig b/core/java/android/view/flags/view_flags.aconfig
index 16e1415..c0d31fa 100644
--- a/core/java/android/view/flags/view_flags.aconfig
+++ b/core/java/android/view/flags/view_flags.aconfig
@@ -46,6 +46,18 @@
}
flag {
+ name: "sensitive_content_premature_protection_removed_fix"
+ namespace: "permissions"
+ description: "Bug fix where sensitive content protection is prematurely removed."
+ bug: "336626172"
+ # Referenced in WM where WM starts before DeviceConfig
+ is_fixed_read_only: true
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
name: "enable_arrow_icon_on_hover_when_clickable"
namespace: "toolkit"
description: "Enable default arrow icon when hovering on buttons or clickable widgets."
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 8174da6..a073873 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -1671,7 +1671,6 @@
@NonNull
@RequiresPermission(value = Manifest.permission.INTERACT_ACROSS_USERS_FULL, conditional = true)
@TestApi
- @FlaggedApi(Flags.FLAG_IMM_USERHANDLE_HOSTSIDETESTS)
@SuppressLint("UserHandle")
public boolean isStylusHandwritingAvailableAsUser(@NonNull UserHandle user) {
final Context fallbackContext = ActivityThread.currentApplication();
@@ -1816,7 +1815,6 @@
@NonNull
@RequiresPermission(value = Manifest.permission.INTERACT_ACROSS_USERS_FULL, conditional = true)
@TestApi
- @FlaggedApi(Flags.FLAG_IMM_USERHANDLE_HOSTSIDETESTS)
@SuppressLint("UserHandle")
public List<InputMethodInfo> getEnabledInputMethodListAsUser(@NonNull UserHandle user) {
return IInputMethodManagerGlobalInvoker.getEnabledInputMethodList(user.getIdentifier());
@@ -1858,7 +1856,6 @@
@NonNull
@RequiresPermission(value = Manifest.permission.INTERACT_ACROSS_USERS_FULL, conditional = true)
@TestApi
- @FlaggedApi(Flags.FLAG_IMM_USERHANDLE_HOSTSIDETESTS)
@SuppressLint("UserHandle")
public List<InputMethodSubtype> getEnabledInputMethodSubtypeListAsUser(
@NonNull String imeId, boolean allowsImplicitlyEnabledSubtypes,
@@ -2464,24 +2461,25 @@
* @hide
*/
public boolean hideSoftInputFromView(@NonNull View view, @HideFlags int flags) {
+ checkFocus();
final boolean isFocusedAndWindowFocused = view.hasWindowFocus() && view.isFocused();
synchronized (mH) {
- if (!isFocusedAndWindowFocused && !hasServedByInputMethodLocked(view)) {
+ final boolean hasServedByInputMethod = hasServedByInputMethodLocked(view);
+ if (!isFocusedAndWindowFocused && !hasServedByInputMethod) {
// Fail early if the view is not focused and not served
// to avoid logging many erroneous calls.
return false;
}
- }
- final int reason = SoftInputShowHideReason.HIDE_SOFT_INPUT_FROM_VIEW;
- final var statsToken = ImeTracker.forLogging().onStart(ImeTracker.TYPE_HIDE,
- ImeTracker.ORIGIN_CLIENT, reason, ImeTracker.isFromUser(view));
- ImeTracker.forLatency().onRequestHide(statsToken,
- ImeTracker.ORIGIN_CLIENT, reason, ActivityThread::currentApplication);
- ImeTracing.getInstance().triggerClientDump("InputMethodManager#hideSoftInputFromView",
- this, null /* icProto */);
- synchronized (mH) {
- if (!hasServedByInputMethodLocked(view)) {
+ final int reason = SoftInputShowHideReason.HIDE_SOFT_INPUT_FROM_VIEW;
+ final var statsToken = ImeTracker.forLogging().onStart(ImeTracker.TYPE_HIDE,
+ ImeTracker.ORIGIN_CLIENT, reason, ImeTracker.isFromUser(view));
+ ImeTracker.forLatency().onRequestHide(statsToken,
+ ImeTracker.ORIGIN_CLIENT, reason, ActivityThread::currentApplication);
+ ImeTracing.getInstance().triggerClientDump("InputMethodManager#hideSoftInputFromView",
+ this, null /* icProto */);
+
+ if (!hasServedByInputMethod) {
ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
ImeTracker.forLatency().onShowFailed(statsToken,
ImeTracker.PHASE_CLIENT_VIEW_SERVED, ActivityThread::currentApplication);
diff --git a/core/java/android/view/inputmethod/flags.aconfig b/core/java/android/view/inputmethod/flags.aconfig
index d79903b..fa9458d 100644
--- a/core/java/android/view/inputmethod/flags.aconfig
+++ b/core/java/android/view/inputmethod/flags.aconfig
@@ -106,3 +106,13 @@
}
}
+flag {
+ name: "defer_show_soft_input_until_session_creation"
+ namespace: "input_method"
+ description: "Defers showSoftInput until the IME session has been created."
+ bug: "337766845"
+ is_fixed_read_only: true
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index f643bd4..5430f8f 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -382,7 +382,7 @@
/**
* Maps Intent ID to RemoteCollectionItems to avoid duplicate items
*/
- private RemoteCollectionCache mCollectionCache = new RemoteCollectionCache();
+ private @NonNull RemoteCollectionCache mCollectionCache = new RemoteCollectionCache();
/** Cache of ApplicationInfos used by collection items. */
private ApplicationInfoCache mApplicationInfoCache = new ApplicationInfoCache();
@@ -775,6 +775,16 @@
}
/**
+ * Return {@code true} only if this {@code RemoteViews} is a legacy list widget that uses
+ * {@code Intent} for inflating child entries.
+ *
+ * @hide
+ */
+ public boolean isLegacyListRemoteViews() {
+ return mCollectionCache.mIdToUriMapping.size() > 0;
+ }
+
+ /**
* Note all {@link Uri} that are referenced internally, with the expectation that Uri permission
* grants will need to be issued to ensure the recipient of this object is able to render its
* contents.
@@ -1231,8 +1241,8 @@
}
private class RemoteCollectionCache {
- private SparseArray<String> mIdToUriMapping = new SparseArray<>();
- private HashMap<String, RemoteCollectionItems> mUriToCollectionMapping = new HashMap<>();
+ private final SparseArray<String> mIdToUriMapping = new SparseArray<>();
+ private final Map<String, RemoteCollectionItems> mUriToCollectionMapping = new HashMap<>();
RemoteCollectionCache() { }
diff --git a/core/java/android/window/TaskFragmentOrganizer.java b/core/java/android/window/TaskFragmentOrganizer.java
index 5c113f8..461eab6 100644
--- a/core/java/android/window/TaskFragmentOrganizer.java
+++ b/core/java/android/window/TaskFragmentOrganizer.java
@@ -18,6 +18,7 @@
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_CLOSE;
+import static android.view.WindowManager.TRANSIT_FIRST_CUSTOM;
import static android.view.WindowManager.TRANSIT_NONE;
import static android.view.WindowManager.TRANSIT_OPEN;
@@ -93,6 +94,19 @@
@TaskFragmentTransitionType
public static final int TASK_FRAGMENT_TRANSIT_CHANGE = TRANSIT_CHANGE;
+
+ /**
+ * The task fragment drag resize transition used by activity embedding.
+ *
+ * This value is also used in Transitions.TRANSIT_TASK_FRAGMENT_DRAG_RESIZE and must not
+ * conflict with other predefined transition types.
+ *
+ * @hide
+ */
+ @WindowManager.TransitionType
+ @TaskFragmentTransitionType
+ public static final int TASK_FRAGMENT_TRANSIT_DRAG_RESIZE = TRANSIT_FIRST_CUSTOM + 17;
+
/**
* Introduced a sub set of {@link WindowManager.TransitionType} for the types that are used for
* TaskFragment transition.
@@ -106,6 +120,7 @@
TASK_FRAGMENT_TRANSIT_OPEN,
TASK_FRAGMENT_TRANSIT_CLOSE,
TASK_FRAGMENT_TRANSIT_CHANGE,
+ TASK_FRAGMENT_TRANSIT_DRAG_RESIZE,
})
@Retention(RetentionPolicy.SOURCE)
public @interface TaskFragmentTransitionType {}
diff --git a/core/java/android/window/WindowOnBackInvokedDispatcher.java b/core/java/android/window/WindowOnBackInvokedDispatcher.java
index cf0c015..e351d6b 100644
--- a/core/java/android/window/WindowOnBackInvokedDispatcher.java
+++ b/core/java/android/window/WindowOnBackInvokedDispatcher.java
@@ -114,7 +114,7 @@
/** Updates the dispatcher state on a new {@link MotionEvent}. */
public void onMotionEvent(MotionEvent ev) {
- if (!isDispatching() || ev == null || ev.getAction() != MotionEvent.ACTION_MOVE) {
+ if (!isBackGestureInProgress() || ev == null || ev.getAction() != MotionEvent.ACTION_MOVE) {
return;
}
mTouchTracker.update(ev.getX(), ev.getY(), Float.NaN, Float.NaN);
@@ -246,9 +246,9 @@
}
/**
- * Indicates if the dispatcher is actively dispatching to a callback.
+ * Indicates if a user gesture is currently in progress.
*/
- public boolean isDispatching() {
+ public boolean isBackGestureInProgress() {
synchronized (mLock) {
return mTouchTracker.isActive() || mImeDispatchingActive;
}
@@ -475,12 +475,17 @@
@Override
public void onBackStarted(BackMotionEvent backEvent) {
mHandler.post(() -> {
+ final OnBackAnimationCallback callback = getBackAnimationCallback();
+
+ // reset progress animator before dispatching onBackStarted to callback. This
+ // ensures that onBackCancelled (of a previous gesture) is always dispatched
+ // before onBackStarted
+ if (callback != null) mProgressAnimator.reset();
mTouchTracker.setState(BackTouchTracker.TouchTrackerState.ACTIVE);
mTouchTracker.setShouldUpdateStartLocation(true);
mTouchTracker.setGestureStartLocation(
backEvent.getTouchX(), backEvent.getTouchY(), backEvent.getSwipeEdge());
- final OnBackAnimationCallback callback = getBackAnimationCallback();
if (callback != null) {
callback.onBackStarted(new BackEvent(
backEvent.getTouchX(),
@@ -499,14 +504,9 @@
public void onBackCancelled() {
mHandler.post(() -> {
final OnBackAnimationCallback callback = getBackAnimationCallback();
- if (callback == null) {
- mTouchTracker.reset();
- return;
- }
- mProgressAnimator.onBackCancelled(() -> {
- mTouchTracker.reset();
- callback.onBackCancelled();
- });
+ mTouchTracker.reset();
+ if (callback == null) return;
+ mProgressAnimator.onBackCancelled(callback::onBackCancelled);
});
}
diff --git a/core/java/android/window/flags/lse_desktop_experience.aconfig b/core/java/android/window/flags/lse_desktop_experience.aconfig
index 55927cc..760c916 100644
--- a/core/java/android/window/flags/lse_desktop_experience.aconfig
+++ b/core/java/android/window/flags/lse_desktop_experience.aconfig
@@ -64,3 +64,17 @@
description: "Hides the App Handle when in fullscreen immersive mode"
bug: "336368019"
}
+
+flag {
+ name: "enable_desktop_windowing_quick_switch"
+ namespace: "lse_desktop_experience"
+ description: "Enables quick switch for desktop mode"
+ bug: "338066529"
+}
+
+flag {
+ name: "enable_additional_windows_above_status_bar"
+ namespace: "lse_desktop_experience"
+ description: "Allows for additional windows tied to WindowDecoration to be layered between status bar and notification shade."
+ bug: "316186265"
+}
diff --git a/core/java/android/window/flags/windowing_sdk.aconfig b/core/java/android/window/flags/windowing_sdk.aconfig
index 945164a..4d1b87a 100644
--- a/core/java/android/window/flags/windowing_sdk.aconfig
+++ b/core/java/android/window/flags/windowing_sdk.aconfig
@@ -120,4 +120,11 @@
metadata {
purpose: PURPOSE_BUGFIX
}
+}
+
+flag {
+ namespace: "windowing_sdk"
+ name: "pip_restore_to_overlay"
+ description: "Restore exit-pip activity back to ActivityEmbedding overlay"
+ bug: "297887697"
}
\ No newline at end of file
diff --git a/core/java/com/android/internal/appwidget/IAppWidgetHost.aidl b/core/java/com/android/internal/appwidget/IAppWidgetHost.aidl
index 7cbacad..8faa4cf 100644
--- a/core/java/com/android/internal/appwidget/IAppWidgetHost.aidl
+++ b/core/java/com/android/internal/appwidget/IAppWidgetHost.aidl
@@ -23,6 +23,7 @@
/** {@hide} */
oneway interface IAppWidgetHost {
+ void updateAppWidgetDeferred(int appWidgetId);
void updateAppWidget(int appWidgetId, in RemoteViews views);
void providerChanged(int appWidgetId, in AppWidgetProviderInfo info);
void providersChanged();
diff --git a/core/java/com/android/internal/content/PackageMonitor.java b/core/java/com/android/internal/content/PackageMonitor.java
index 7ac553c..ad73294 100644
--- a/core/java/com/android/internal/content/PackageMonitor.java
+++ b/core/java/com/android/internal/content/PackageMonitor.java
@@ -22,6 +22,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.Flags;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
@@ -68,7 +69,8 @@
@UnsupportedAppUsage
public PackageMonitor() {
- this(true);
+ // If the feature flag is enabled, set mSupportsPackageRestartQuery to false by default
+ this(!Flags.packageRestartQueryDisabledByDefault());
}
/**
@@ -164,6 +166,13 @@
}
/**
+ * Same as {@link #onPackageAdded(String, int)}, but this callback
+ * has extras passed in.
+ */
+ public void onPackageAddedWithExtras(String packageName, int uid, Bundle extras) {
+ }
+
+ /**
* Called when a package is really removed (and not replaced).
*/
@UnsupportedAppUsage
@@ -171,19 +180,47 @@
}
/**
+ * Same as {@link #onPackageRemoved(String, int)}, but this callback
+ * has extras passed in.
+ */
+ public void onPackageRemovedWithExtras(String packageName, int uid, Bundle extras) {
+ }
+
+ /**
* Called when a package is really removed (and not replaced) for
* all users on the device.
*/
public void onPackageRemovedAllUsers(String packageName, int uid) {
}
+ /**
+ * Same as {@link #onPackageRemovedAllUsers(String, int)}, but this callback
+ * has extras passed in.
+ */
+ public void onPackageRemovedAllUsersWithExtras(String packageName, int uid, Bundle extras) {
+ }
+
public void onPackageUpdateStarted(String packageName, int uid) {
}
+ /**
+ * Same as {@link #onPackageUpdateStarted(String, int)}, but this callback
+ * has extras passed in.
+ */
+ public void onPackageUpdateStartedWithExtras(String packageName, int uid, Bundle extras) {
+ }
+
public void onPackageUpdateFinished(String packageName, int uid) {
}
/**
+ * Same as {@link #onPackageUpdateFinished(String, int)}, but this callback
+ * has extras passed in.
+ */
+ public void onPackageUpdateFinishedWithExtras(String packageName, int uid, Bundle extras) {
+ }
+
+ /**
* Direct reflection of {@link Intent#ACTION_PACKAGE_CHANGED
* Intent.ACTION_PACKAGE_CHANGED} being received, informing you of
* changes to the enabled/disabled state of components in a package
@@ -281,6 +318,13 @@
}
/**
+ * Same as {@link #onPackageModified(String)}, but this callback
+ * has extras passed in.
+ */
+ public void onPackageModifiedWithExtras(@NonNull String packageName, Bundle extras) {
+ }
+
+ /**
* Called when a package in the stopped state is started for some reason.
*
* @param packageName Name of the package that was unstopped
@@ -423,10 +467,13 @@
mModifiedPackages = mTempArray;
mChangeType = PACKAGE_UPDATING;
onPackageUpdateFinished(pkg, uid);
+ onPackageUpdateFinishedWithExtras(pkg, uid, intent.getExtras());
onPackageModified(pkg);
+ onPackageModifiedWithExtras(pkg, intent.getExtras());
} else {
mChangeType = PACKAGE_PERMANENT_CHANGE;
onPackageAdded(pkg, uid);
+ onPackageAddedWithExtras(pkg, uid, intent.getExtras());
}
onPackageAppearedWithExtras(pkg, intent.getExtras());
onPackageAppeared(pkg, mChangeType);
@@ -440,11 +487,13 @@
if (intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
mChangeType = PACKAGE_UPDATING;
onPackageUpdateStarted(pkg, uid);
+ onPackageUpdateStartedWithExtras(pkg, uid, intent.getExtras());
if (intent.getBooleanExtra(Intent.EXTRA_ARCHIVAL, false)) {
// In case it is a removal event due to archiving, we trigger package
// update event to refresh details like icons, title etc. corresponding to
// the archived app.
onPackageModified(pkg);
+ onPackageModifiedWithExtras(pkg, intent.getExtras());
}
} else {
mChangeType = PACKAGE_PERMANENT_CHANGE;
@@ -453,8 +502,10 @@
// it when it is re-added.
mSomePackagesChanged = true;
onPackageRemoved(pkg, uid);
+ onPackageRemovedWithExtras(pkg, uid, intent.getExtras());
if (intent.getBooleanExtra(Intent.EXTRA_REMOVED_FOR_ALL_USERS, false)) {
onPackageRemovedAllUsers(pkg, uid);
+ onPackageRemovedAllUsersWithExtras(pkg, uid, intent.getExtras());
}
}
onPackageDisappearedWithExtras(pkg, intent.getExtras());
@@ -474,6 +525,7 @@
}
onPackageChangedWithExtras(pkg, intent.getExtras());
onPackageModified(pkg);
+ onPackageModifiedWithExtras(pkg, intent.getExtras());
}
} else if (Intent.ACTION_PACKAGE_DATA_CLEARED.equals(action)) {
String pkg = getPackageName(intent);
diff --git a/core/java/com/android/internal/inputmethod/ImeTracing.java b/core/java/com/android/internal/inputmethod/ImeTracing.java
index db95012..cd4ccda 100644
--- a/core/java/com/android/internal/inputmethod/ImeTracing.java
+++ b/core/java/com/android/internal/inputmethod/ImeTracing.java
@@ -16,6 +16,7 @@
package com.android.internal.inputmethod;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.app.ActivityThread;
@@ -59,7 +60,9 @@
*/
public static ImeTracing getInstance() {
if (sInstance == null) {
- if (isSystemProcess()) {
+ if (android.tracing.Flags.perfettoIme()) {
+ sInstance = new ImeTracingPerfettoImpl();
+ } else if (isSystemProcess()) {
sInstance = new ImeTracingServerImpl();
} else {
sInstance = new ImeTracingClientImpl();
@@ -77,7 +80,7 @@
* and {@see #IME_TRACING_FROM_IMS}
* @param where
*/
- public void sendToService(byte[] protoDump, int source, String where) {
+ protected void sendToService(byte[] protoDump, int source, String where) {
InputMethodManagerGlobal.startProtoDump(protoDump, source, where,
e -> Log.e(TAG, "Exception while sending ime-related dump to server", e));
}
@@ -144,7 +147,7 @@
*
* @param where Place where the trace was triggered.
*/
- public abstract void triggerManagerServiceDump(String where);
+ public abstract void triggerManagerServiceDump(String where, @NonNull ServiceDumper dumper);
/**
* Being called while taking a bugreport so that tracing files can be included in the bugreport
diff --git a/core/java/com/android/internal/inputmethod/ImeTracingClientImpl.java b/core/java/com/android/internal/inputmethod/ImeTracingClientImpl.java
index 95ed4ed..8a684d3 100644
--- a/core/java/com/android/internal/inputmethod/ImeTracingClientImpl.java
+++ b/core/java/com/android/internal/inputmethod/ImeTracingClientImpl.java
@@ -83,7 +83,7 @@
}
@Override
- public void triggerManagerServiceDump(String where) {
+ public void triggerManagerServiceDump(String where, @NonNull ServiceDumper dumper) {
// Intentionally left empty, this is implemented in ImeTracingServerImpl
}
diff --git a/core/java/com/android/internal/inputmethod/ImeTracingPerfettoImpl.java b/core/java/com/android/internal/inputmethod/ImeTracingPerfettoImpl.java
new file mode 100644
index 0000000..91b80dd
--- /dev/null
+++ b/core/java/com/android/internal/inputmethod/ImeTracingPerfettoImpl.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.inputmethod;
+
+import static android.tracing.perfetto.DataSourceParams.PERFETTO_DS_BUFFER_EXHAUSTED_POLICY_STALL_AND_ABORT;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.internal.perfetto.protos.Inputmethodeditor.InputMethodClientsTraceProto;
+import android.internal.perfetto.protos.Inputmethodeditor.InputMethodManagerServiceTraceProto;
+import android.internal.perfetto.protos.Inputmethodeditor.InputMethodServiceTraceProto;
+import android.internal.perfetto.protos.TracePacketOuterClass.TracePacket;
+import android.internal.perfetto.protos.WinscopeExtensionsImplOuterClass.WinscopeExtensionsImpl;
+import android.os.SystemClock;
+import android.os.Trace;
+import android.tracing.inputmethod.InputMethodDataSource;
+import android.tracing.perfetto.DataSourceParams;
+import android.tracing.perfetto.InitArguments;
+import android.tracing.perfetto.Producer;
+import android.util.proto.ProtoOutputStream;
+import android.view.inputmethod.InputMethodManager;
+
+import java.io.PrintWriter;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * An implementation of {@link ImeTracing} for perfetto tracing.
+ */
+final class ImeTracingPerfettoImpl extends ImeTracing {
+ private final AtomicInteger mTracingSessionsCount = new AtomicInteger(0);
+ private final AtomicBoolean mIsClientDumpInProgress = new AtomicBoolean(false);
+ private final AtomicBoolean mIsServiceDumpInProgress = new AtomicBoolean(false);
+ private final AtomicBoolean mIsManagerServiceDumpInProgress = new AtomicBoolean(false);
+ private final InputMethodDataSource mDataSource = new InputMethodDataSource(
+ mTracingSessionsCount::incrementAndGet,
+ mTracingSessionsCount::decrementAndGet);
+
+ ImeTracingPerfettoImpl() {
+ Producer.init(InitArguments.DEFAULTS);
+ mDataSource.register(
+ new DataSourceParams(PERFETTO_DS_BUFFER_EXHAUSTED_POLICY_STALL_AND_ABORT));
+ }
+
+
+ @Override
+ public void triggerClientDump(String where, InputMethodManager immInstance,
+ @Nullable byte[] icProto) {
+ if (!isEnabled() || !isAvailable()) {
+ return;
+ }
+
+ if (!mIsClientDumpInProgress.compareAndSet(false, true)) {
+ return;
+ }
+
+ if (immInstance == null) {
+ return;
+ }
+
+ try {
+ Trace.beginSection("inputmethod_client_dump");
+ mDataSource.trace((ctx) -> {
+ final ProtoOutputStream os = ctx.newTracePacket();
+ os.write(TracePacket.TIMESTAMP, SystemClock.elapsedRealtimeNanos());
+ final long tokenWinscopeExtensions =
+ os.start(TracePacket.WINSCOPE_EXTENSIONS);
+ final long tokenExtensionsField =
+ os.start(WinscopeExtensionsImpl.INPUTMETHOD_CLIENTS);
+ os.write(InputMethodClientsTraceProto.WHERE, where);
+ final long tokenClient =
+ os.start(InputMethodClientsTraceProto.CLIENT);
+ immInstance.dumpDebug(os, icProto);
+ os.end(tokenClient);
+ os.end(tokenExtensionsField);
+ os.end(tokenWinscopeExtensions);
+ });
+ } finally {
+ mIsClientDumpInProgress.set(false);
+ Trace.endSection();
+ }
+ }
+
+ @Override
+ public void triggerServiceDump(String where,
+ @NonNull ServiceDumper dumper, @Nullable byte[] icProto) {
+ if (!isEnabled() || !isAvailable()) {
+ return;
+ }
+
+ if (!mIsServiceDumpInProgress.compareAndSet(false, true)) {
+ return;
+ }
+
+ try {
+ Trace.beginSection("inputmethod_service_dump");
+ mDataSource.trace((ctx) -> {
+ final ProtoOutputStream os = ctx.newTracePacket();
+ os.write(TracePacket.TIMESTAMP, SystemClock.elapsedRealtimeNanos());
+ final long tokenWinscopeExtensions =
+ os.start(TracePacket.WINSCOPE_EXTENSIONS);
+ final long tokenExtensionsField =
+ os.start(WinscopeExtensionsImpl.INPUTMETHOD_SERVICE);
+ os.write(InputMethodServiceTraceProto.WHERE, where);
+ dumper.dumpToProto(os, icProto);
+ os.end(tokenExtensionsField);
+ os.end(tokenWinscopeExtensions);
+ });
+ } finally {
+ mIsServiceDumpInProgress.set(false);
+ Trace.endSection();
+ }
+ }
+
+ @Override
+ public void triggerManagerServiceDump(@NonNull String where, @NonNull ServiceDumper dumper) {
+ if (!isEnabled() || !isAvailable()) {
+ return;
+ }
+
+ if (!mIsManagerServiceDumpInProgress.compareAndSet(false, true)) {
+ return;
+ }
+
+ try {
+ Trace.beginSection("inputmethod_manager_service_dump");
+ mDataSource.trace((ctx) -> {
+ final ProtoOutputStream os = ctx.newTracePacket();
+ os.write(TracePacket.TIMESTAMP, SystemClock.elapsedRealtimeNanos());
+ final long tokenWinscopeExtensions =
+ os.start(TracePacket.WINSCOPE_EXTENSIONS);
+ final long tokenExtensionsField =
+ os.start(WinscopeExtensionsImpl.INPUTMETHOD_MANAGER_SERVICE);
+ os.write(InputMethodManagerServiceTraceProto.WHERE, where);
+ dumper.dumpToProto(os, null);
+ os.end(tokenExtensionsField);
+ os.end(tokenWinscopeExtensions);
+ });
+ } finally {
+ mIsManagerServiceDumpInProgress.set(false);
+ Trace.endSection();
+ }
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return mTracingSessionsCount.get() > 0;
+ }
+
+ @Override
+ public void startTrace(@Nullable PrintWriter pw) {
+ // Intentionally left empty. Tracing start/stop is managed through Perfetto.
+ }
+
+ @Override
+ public void stopTrace(@Nullable PrintWriter pw) {
+ // Intentionally left empty. Tracing start/stop is managed through Perfetto.
+ }
+
+ @Override
+ public void addToBuffer(ProtoOutputStream proto, int source) {
+ // Intentionally left empty. Only used for legacy tracing.
+ }
+}
diff --git a/core/java/com/android/internal/inputmethod/ImeTracingServerImpl.java b/core/java/com/android/internal/inputmethod/ImeTracingServerImpl.java
index edd74f6..937f94c 100644
--- a/core/java/com/android/internal/inputmethod/ImeTracingServerImpl.java
+++ b/core/java/com/android/internal/inputmethod/ImeTracingServerImpl.java
@@ -18,6 +18,7 @@
import static android.os.Build.IS_USER;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.SystemClock;
import android.util.Log;
@@ -116,7 +117,7 @@
}
@Override
- public void triggerManagerServiceDump(String where) {
+ public void triggerManagerServiceDump(String where, @NonNull ServiceDumper dumper) {
if (!isEnabled() || !isAvailable()) {
return;
}
diff --git a/core/java/com/android/internal/jank/Cuj.java b/core/java/com/android/internal/jank/Cuj.java
index f2d2c1b..6ffa826 100644
--- a/core/java/com/android/internal/jank/Cuj.java
+++ b/core/java/com/android/internal/jank/Cuj.java
@@ -134,10 +134,12 @@
public static final int CUJ_LAUNCHER_WIDGET_PICKER_SEARCH_BACK = 99;
public static final int CUJ_LAUNCHER_WIDGET_BOTTOM_SHEET_CLOSE_BACK = 100;
public static final int CUJ_LAUNCHER_WIDGET_EDU_SHEET_CLOSE_BACK = 101;
+ public static final int CUJ_LAUNCHER_PRIVATE_SPACE_LOCK = 102;
+ public static final int CUJ_LAUNCHER_PRIVATE_SPACE_UNLOCK = 103;
// When adding a CUJ, update this and make sure to also update CUJ_TO_STATSD_INTERACTION_TYPE.
@VisibleForTesting
- static final int LAST_CUJ = CUJ_LAUNCHER_WIDGET_EDU_SHEET_CLOSE_BACK;
+ static final int LAST_CUJ = CUJ_LAUNCHER_PRIVATE_SPACE_UNLOCK;
/** @hide */
@IntDef({
@@ -230,7 +232,9 @@
CUJ_LAUNCHER_TASKBAR_ALL_APPS_SEARCH_BACK,
CUJ_LAUNCHER_WIDGET_PICKER_CLOSE_BACK,
CUJ_LAUNCHER_WIDGET_PICKER_SEARCH_BACK,
- CUJ_LAUNCHER_WIDGET_BOTTOM_SHEET_CLOSE_BACK
+ CUJ_LAUNCHER_WIDGET_BOTTOM_SHEET_CLOSE_BACK,
+ CUJ_LAUNCHER_PRIVATE_SPACE_LOCK,
+ CUJ_LAUNCHER_PRIVATE_SPACE_UNLOCK
})
@Retention(RetentionPolicy.SOURCE)
public @interface CujType {
@@ -335,6 +339,8 @@
CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_WIDGET_PICKER_SEARCH_BACK] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_WIDGET_PICKER_SEARCH_BACK;
CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_WIDGET_BOTTOM_SHEET_CLOSE_BACK] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_WIDGET_BOTTOM_SHEET_CLOSE_BACK;
CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_WIDGET_EDU_SHEET_CLOSE_BACK] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_WIDGET_EDU_SHEET_CLOSE_BACK;
+ CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_PRIVATE_SPACE_LOCK] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_PRIVATE_SPACE_LOCK;
+ CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_PRIVATE_SPACE_UNLOCK] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_PRIVATE_SPACE_UNLOCK;
}
private Cuj() {
@@ -533,6 +539,10 @@
return "LAUNCHER_WIDGET_BOTTOM_SHEET_CLOSE_BACK";
case CUJ_LAUNCHER_WIDGET_EDU_SHEET_CLOSE_BACK:
return "LAUNCHER_WIDGET_EDU_SHEET_CLOSE_BACK";
+ case CUJ_LAUNCHER_PRIVATE_SPACE_LOCK:
+ return "LAUNCHER_PRIVATE_SPACE_LOCK";
+ case CUJ_LAUNCHER_PRIVATE_SPACE_UNLOCK:
+ return "LAUNCHER_PRIVATE_SPACE_UNLOCK";
}
return "UNKNOWN";
}
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index f4315e3..74c2325 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -523,8 +523,8 @@
ViewRootImpl viewRootImpl = getViewRootImpl();
if (viewRootImpl != null) {
viewRootImpl.getOnBackInvokedDispatcher().onMotionEvent(event);
- // Intercept touch if back dispatching is active.
- if (viewRootImpl.getOnBackInvokedDispatcher().isDispatching()) {
+ // Intercept touch if back gesture is in progress.
+ if (viewRootImpl.getOnBackInvokedDispatcher().isBackGestureInProgress()) {
return true;
}
}
diff --git a/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java b/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java
index 874cc49..ee33eb4 100644
--- a/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java
+++ b/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java
@@ -99,7 +99,7 @@
private final Map<LogLevel, Integer> mDefaultLogLevelCounts = new ArrayMap<>();
private final Map<IProtoLogGroup, Map<LogLevel, Integer>> mLogLevelCounts = new ArrayMap<>();
- private final ExecutorService mBackgroundLoggingService = Executors.newCachedThreadPool();
+ private final ExecutorService mBackgroundLoggingService = Executors.newSingleThreadExecutor();
public PerfettoProtoLogImpl(String viewerConfigFilePath,
TreeMap<String, IProtoLogGroup> logGroups, Runnable cacheUpdater) {
diff --git a/core/java/com/android/internal/util/ProcFileReader.java b/core/java/com/android/internal/util/ProcFileReader.java
index 6cf241e..ddbb586 100644
--- a/core/java/com/android/internal/util/ProcFileReader.java
+++ b/core/java/com/android/internal/util/ProcFileReader.java
@@ -89,6 +89,12 @@
mTail -= count;
if (mTail == 0) {
fillBuf();
+
+ if (mTail > 0 && mBuffer[0] == ' ') {
+ // After filling the buffer, it contains more consecutive
+ // delimiters that need to be skipped.
+ consumeBuf(0);
+ }
}
}
diff --git a/core/java/com/android/internal/widget/LockPatternView.java b/core/java/com/android/internal/widget/LockPatternView.java
index 66b0158..0734e68 100644
--- a/core/java/com/android/internal/widget/LockPatternView.java
+++ b/core/java/com/android/internal/widget/LockPatternView.java
@@ -886,9 +886,16 @@
cellState.activationAnimator.cancel();
}
AnimatorSet animatorSet = new AnimatorSet();
+
+ // When running the line end animation (see doc for createLineEndAnimation), if cell is in:
+ // - activate state - use finger position at the time of hit detection
+ // - deactivate state - use current position where the end was last during initial animation
+ // Note that deactivate state will only come if mKeepDotActivated is themed true.
+ final float startX = activate == CELL_ACTIVATE ? mInProgressX : cellState.lineEndX;
+ final float startY = activate == CELL_ACTIVATE ? mInProgressY : cellState.lineEndY;
AnimatorSet.Builder animatorSetBuilder = animatorSet
.play(createLineDisappearingAnimation())
- .with(createLineEndAnimation(cellState, mInProgressX, mInProgressY,
+ .with(createLineEndAnimation(cellState, startX, startY,
getCenterXForColumn(cell.column), getCenterYForRow(cell.row)));
if (mDotSize != mDotSizeActivated) {
animatorSetBuilder.with(createDotRadiusAnimation(cellState));
diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp
index 72b98a2..2316f4c 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -529,7 +529,7 @@
}
static void android_hardware_Camera_getCameraInfo(JNIEnv *env, jobject thiz, jint cameraId,
- jboolean overrideToPortrait, jint deviceId,
+ jint rotationOverride, jint deviceId,
jint devicePolicy, jobject info_obj) {
CameraInfo cameraInfo;
if (cameraId >= Camera::getNumberOfCameras(deviceId, devicePolicy) || cameraId < 0) {
@@ -538,7 +538,7 @@
return;
}
- status_t rc = Camera::getCameraInfo(cameraId, overrideToPortrait, deviceId, devicePolicy,
+ status_t rc = Camera::getCameraInfo(cameraId, rotationOverride, deviceId, devicePolicy,
&cameraInfo);
if (rc != NO_ERROR) {
jniThrowRuntimeException(env, "Fail to get camera info");
@@ -557,7 +557,7 @@
// connect to camera service
static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz, jobject weak_this,
jint cameraId, jstring clientPackageName,
- jboolean overrideToPortrait,
+ jint rotationOverride,
jboolean forceSlowJpegMode, jint deviceId,
jint devicePolicy) {
// Convert jstring to String16
@@ -571,7 +571,7 @@
int targetSdkVersion = android_get_application_target_sdk_version();
sp<Camera> camera =
Camera::connect(cameraId, clientName, Camera::USE_CALLING_UID, Camera::USE_CALLING_PID,
- targetSdkVersion, overrideToPortrait, forceSlowJpegMode, deviceId,
+ targetSdkVersion, rotationOverride, forceSlowJpegMode, deviceId,
devicePolicy);
if (camera == NULL) {
return -EACCES;
@@ -600,7 +600,7 @@
// Update default display orientation in case the sensor is reverse-landscape
CameraInfo cameraInfo;
- status_t rc = Camera::getCameraInfo(cameraId, overrideToPortrait, deviceId, devicePolicy,
+ status_t rc = Camera::getCameraInfo(cameraId, rotationOverride, deviceId, devicePolicy,
&cameraInfo);
if (rc != NO_ERROR) {
ALOGE("%s: getCameraInfo error: %d", __FUNCTION__, rc);
@@ -1057,9 +1057,9 @@
static const JNINativeMethod camMethods[] = {
{"_getNumberOfCameras", "(II)I", (void *)android_hardware_Camera_getNumberOfCameras},
- {"_getCameraInfo", "(IZIILandroid/hardware/Camera$CameraInfo;)V",
+ {"_getCameraInfo", "(IIIILandroid/hardware/Camera$CameraInfo;)V",
(void *)android_hardware_Camera_getCameraInfo},
- {"native_setup", "(Ljava/lang/Object;ILjava/lang/String;ZZII)I",
+ {"native_setup", "(Ljava/lang/Object;ILjava/lang/String;IZII)I",
(void *)android_hardware_Camera_native_setup},
{"native_release", "()V", (void *)android_hardware_Camera_release},
{"setPreviewSurface", "(Landroid/view/Surface;)V",
diff --git a/core/jni/android_os_HwParcel.cpp b/core/jni/android_os_HwParcel.cpp
index 0e3c510..c786652 100644
--- a/core/jni/android_os_HwParcel.cpp
+++ b/core/jni/android_os_HwParcel.cpp
@@ -235,6 +235,10 @@
return mWasSent;
}
+void JHwParcel::addBlob(const sp<JHwBlob> &blob) {
+ mBlobs.emplace_back(blob);
+}
+
} // namespace android
////////////////////////////////////////////////////////////////////////////////
@@ -1059,6 +1063,7 @@
JHwParcel::GetNativeContext(env, thiz)->getParcel();
sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, blobObj);
+ JHwParcel::GetNativeContext(env, thiz)->addBlob(blob);
status_t err = blob->writeToParcel(parcel);
if (err != OK) {
diff --git a/core/jni/android_os_HwParcel.h b/core/jni/android_os_HwParcel.h
index 2c26993..07d144a 100644
--- a/core/jni/android_os_HwParcel.h
+++ b/core/jni/android_os_HwParcel.h
@@ -17,14 +17,15 @@
#ifndef ANDROID_OS_HW_PARCEL_H
#define ANDROID_OS_HW_PARCEL_H
-#include "hwbinder/EphemeralStorage.h"
-
#include <android-base/macros.h>
#include <hwbinder/IBinder.h>
#include <hwbinder/Parcel.h>
#include <jni.h>
#include <utils/RefBase.h>
+#include "android_os_HwBlob.h"
+#include "hwbinder/EphemeralStorage.h"
+
namespace android {
struct JHwParcel : public RefBase {
@@ -44,6 +45,8 @@
EphemeralStorage *getStorage();
+ void addBlob(const sp<JHwBlob> &blob);
+
void setTransactCallback(::android::hardware::IBinder::TransactCallback cb);
void send();
@@ -60,6 +63,7 @@
::android::hardware::IBinder::TransactCallback mTransactCallback;
bool mWasSent;
+ std::vector<sp<JHwBlob>> mBlobs;
DISALLOW_COPY_AND_ASSIGN(JHwParcel);
};
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 3ed9f49..12d62cc 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -1828,10 +1828,10 @@
std::string source = "/dev/__properties__/appcompat_override";
std::string target = "/dev/__properties__";
if (access(source.c_str(), F_OK) != 0) {
- fail_fn(CREATE_ERROR("Error accessing %s: %s", source.c_str(), strerror(errno)));
+ return;
}
if (access(target.c_str(), F_OK) != 0) {
- fail_fn(CREATE_ERROR("Error accessing %s: %s", target.c_str(), strerror(errno)));
+ return;
}
BindMount(source, target, fail_fn);
// Reload the system properties file, to ensure new values are read into memory
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 77a9912..bfbfb3a 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -178,6 +178,7 @@
<protected-broadcast android:name="android.bluetooth.device.action.CONNECTION_ACCESS_REPLY" />
<protected-broadcast android:name="android.bluetooth.device.action.CONNECTION_ACCESS_CANCEL" />
<protected-broadcast android:name="android.bluetooth.device.action.CONNECTION_ACCESS_REQUEST" />
+ <protected-broadcast android:name="android.bluetooth.device.action.KEY_MISSING" />
<protected-broadcast android:name="android.bluetooth.device.action.SDP_RECORD" />
<protected-broadcast android:name="android.bluetooth.device.action.BATTERY_LEVEL_CHANGED" />
<protected-broadcast android:name="android.bluetooth.device.action.REMOTE_ISSUE_OCCURRED" />
diff --git a/core/res/res/drawable-nodpi/stat_sys_adb.xml b/core/res/res/drawable-nodpi/stat_sys_adb.xml
index 8ae2a9b..6ce4b9d 100644
--- a/core/res/res/drawable-nodpi/stat_sys_adb.xml
+++ b/core/res/res/drawable-nodpi/stat_sys_adb.xml
@@ -21,16 +21,102 @@
android:viewportHeight="24">
<group>
<clip-path
- android:pathData="M12,20.923C10.764,20.923 9.946,20.065 9.131,18.653C8.316,17.241 4.291,10.269 3.476,8.857C2.66,7.445 2.326,6.309 2.944,5.238C3.563,4.167 4.714,3.888 6.344,3.888C7.975,3.888 16.025,3.888 17.656,3.888C19.286,3.888 20.437,4.167 21.056,5.238C21.674,6.309 21.34,7.445 20.524,8.857C19.709,10.269 15.684,17.241 14.869,18.653C14.054,20.065 13.236,20.923 12,20.923H12Z"/>
+ android:pathData="
+ M12.6495 17.375
+ C12.3608 17.875 11.6392 17.875 11.3505 17.375
+ L3.98927 4.625
+ C3.70059 4.125 4.06143 3.5 4.63878 3.5
+ L19.3612 3.5
+ C19.9386 3.5 20.2994 4.125 20.0107 4.625
+ L12.6495 17.375
+ Z
+ "/>
<path
- android:pathData="M5,14.978h14v9.8h-14z"
+ android:pathData="M5,12 h14v9.8h-14z"
android:fillColor="#ffffff"/>
<path
- android:pathData="M18.722,15.576C18.717,15.548 18.713,15.521 18.708,15.493C18.68,15.324 18.646,15.156 18.605,14.991C18.534,14.701 18.445,14.42 18.339,14.146C18.249,13.915 18.146,13.69 18.033,13.472C17.886,13.192 17.722,12.923 17.539,12.667C17.316,12.354 17.067,12.06 16.795,11.789C16.68,11.676 16.562,11.566 16.44,11.461C16.175,11.233 15.893,11.025 15.595,10.839C15.598,10.834 15.6,10.83 15.602,10.825C15.739,10.59 15.875,10.355 16.012,10.119C16.145,9.889 16.279,9.659 16.412,9.429C16.508,9.264 16.604,9.098 16.699,8.933C16.722,8.894 16.74,8.854 16.753,8.812C16.791,8.696 16.792,8.575 16.762,8.462C16.754,8.434 16.745,8.406 16.734,8.38C16.723,8.353 16.71,8.327 16.695,8.302C16.644,8.216 16.571,8.142 16.479,8.087C16.399,8.039 16.308,8.011 16.215,8.002C16.176,7.999 16.137,7.999 16.098,8.003C16.066,8.007 16.034,8.013 16.002,8.021C15.889,8.051 15.785,8.113 15.703,8.202C15.674,8.235 15.647,8.27 15.624,8.309C15.529,8.475 15.433,8.64 15.337,8.805L14.937,9.495C14.801,9.731 14.664,9.966 14.528,10.202C14.513,10.227 14.498,10.253 14.483,10.279C14.462,10.271 14.442,10.263 14.421,10.255C13.669,9.968 12.853,9.811 12,9.811C11.977,9.811 11.954,9.811 11.931,9.811C11.172,9.819 10.444,9.951 9.764,10.188C9.686,10.215 9.608,10.244 9.531,10.274C9.517,10.25 9.503,10.226 9.489,10.202C9.353,9.966 9.216,9.731 9.08,9.495C8.946,9.265 8.813,9.035 8.679,8.805C8.584,8.64 8.488,8.475 8.392,8.31C8.37,8.271 8.343,8.235 8.314,8.203C8.232,8.113 8.127,8.051 8.014,8.021C7.983,8.013 7.951,8.007 7.919,8.004C7.88,8 7.841,7.999 7.802,8.003C7.709,8.011 7.618,8.039 7.537,8.088C7.446,8.142 7.373,8.217 7.322,8.302C7.307,8.327 7.294,8.353 7.283,8.38C7.271,8.407 7.262,8.434 7.255,8.462C7.225,8.575 7.226,8.697 7.264,8.812C7.277,8.854 7.295,8.894 7.318,8.934C7.413,9.099 7.509,9.264 7.605,9.429C7.738,9.659 7.872,9.889 8.005,10.119C8.141,10.355 8.278,10.59 8.414,10.826C8.415,10.828 8.417,10.83 8.418,10.832C8.143,11.003 7.881,11.192 7.634,11.4C7.486,11.524 7.343,11.654 7.207,11.79C6.935,12.061 6.685,12.354 6.462,12.668C6.279,12.923 6.114,13.192 5.968,13.472C5.855,13.691 5.752,13.915 5.662,14.147C5.556,14.42 5.467,14.702 5.396,14.991C5.355,15.157 5.321,15.324 5.293,15.494C5.288,15.521 5.284,15.549 5.279,15.576C5.264,15.675 5.251,15.774 5.241,15.874L18.759,15.874C18.749,15.774 18.736,15.675 18.72,15.576L18.722,15.576Z"
+ android:pathData="
+ M15.97 10.48
+ C15.97 10.46 15.97 10.45 15.96 10.43
+ C15.95 10.33 15.93 10.23 15.90 10.13
+ C15.86 9.96 15.81 9.79 15.75 9.63
+ C15.69 9.50 15.63 9.36 15.57 9.23
+ C15.48 9.07 15.38 8.91 15.27 8.76
+ C15.14 8.57 14.99 8.40 14.83 8.24
+ C14.76 8.17 14.69 8.11 14.62 8.04
+ C14.47 7.91 14.30 7.78 14.12 7.67
+ C14.12 7.67 14.13 7.67 14.13 7.67
+ C14.21 7.53 14.29 7.39 14.37 7.25
+ C14.45 7.11 14.53 6.98 14.61 6.84
+ C14.66 6.74 14.72 6.64 14.78 6.55
+ C14.79 6.52 14.80 6.50 14.81 6.48
+ C14.83 6.41 14.83 6.33 14.81 6.27
+ C14.81 6.25 14.80 6.24 14.80 6.22
+ C14.79 6.20 14.78 6.19 14.77 6.17
+ C14.74 6.12 14.70 6.08 14.65 6.05
+ C14.60 6.02 14.54 6 14.49 6
+ C14.47 5.99 14.44 5.99 14.42 6
+ C14.40 6 14.38 6 14.36 6.01
+ C14.30 6.02 14.23 6.06 14.19 6.11
+ C14.17 6.13 14.15 6.15 14.14 6.18
+ C14.08 6.28 14.03 6.37 13.97 6.47
+ L13.73 6.88
+ C13.65 7.02 13.57 7.16 13.49 7.30
+ C13.48 7.31 13.47 7.33 13.46 7.34
+ C13.45 7.34 13.44 7.33 13.43 7.33
+ C12.98 7.16 12.50 7.07 12 7.07
+ C11.98 7.07 11.97 7.07 11.95 7.07
+ C11.51 7.07 11.07 7.15 10.67 7.29
+ C10.63 7.31 10.58 7.32 10.53 7.34
+ C10.53 7.33 10.52 7.31 10.51 7.30
+ C10.43 7.16 10.35 7.02 10.27 6.88
+ C10.19 6.74 10.11 6.61 10.03 6.47
+ C9.97 6.37 9.92 6.28 9.86 6.18
+ C9.85 6.15 9.83 6.13 9.81 6.11
+ C9.77 6.06 9.70 6.03 9.64 6.01
+ C9.62 6 9.60 6 9.58 6
+ C9.56 5.99 9.53 5.99 9.51 6
+ C9.46 6 9.40 6.02 9.35 6.05
+ C9.30 6.08 9.26 6.12 9.23 6.17
+ C9.22 6.19 9.21 6.20 9.20 6.22
+ C9.20 6.24 9.19 6.25 9.19 6.27
+ C9.17 6.34 9.17 6.41 9.19 6.48
+ C9.20 6.50 9.21 6.52 9.22 6.55
+ C9.28 6.65 9.34 6.74 9.39 6.84
+ C9.47 6.98 9.55 7.11 9.63 7.25
+ C9.71 7.39 9.79 7.53 9.87 7.67
+ C9.87 7.67 9.87 7.67 9.88 7.67
+ C9.71 7.77 9.56 7.88 9.41 8.01
+ C9.32 8.08 9.24 8.16 9.16 8.24
+ C9 8.40 8.85 8.57 8.72 8.76
+ C8.61 8.91 8.51 9.07 8.43 9.23
+ C8.36 9.36 8.30 9.50 8.24 9.63
+ C8.18 9.79 8.13 9.96 8.09 10.13
+ C8.06 10.23 8.04 10.33 8.03 10.43
+ C8.02 10.45 8.02 10.46 8.02 10.48
+ C8.01 10.54 8 10.60 8 10.65
+ L16 10.65
+ C15.99 10.60 15.98 10.54 15.97 10.48
+ L15.97 10.48
+ Z
+ "
android:fillColor="#ffffff"/>
</group>
<path
- android:pathData="M12,20.923C10.764,20.923 9.946,20.065 9.131,18.653C8.316,17.241 4.291,10.269 3.476,8.857C2.66,7.445 2.326,6.309 2.944,5.238C3.563,4.167 4.714,3.888 6.344,3.888C7.975,3.888 16.025,3.888 17.656,3.888C19.286,3.888 20.437,4.167 21.056,5.238C21.674,6.309 21.34,7.445 20.524,8.857C19.709,10.269 15.684,17.241 14.869,18.653C14.054,20.065 13.236,20.923 12,20.923H12Z"
+ android:pathData="
+ M12,20.923
+ C10.764,20.923 9.946,20.065 9.131,18.653
+ C8.316,17.241 4.291,10.269 3.476,8.857
+ C2.66,7.445 2.326,6.309 2.944,5.238
+ C3.563,4.167 4.714,3.888 6.344,3.888
+ C7.975,3.888 16.025,3.888 17.656,3.888
+ C19.286,3.888 20.437,4.167 21.056,5.238
+ C21.674,6.309 21.34,7.445 20.524,8.857
+ C19.709,10.269 15.684,17.241 14.869,18.653
+ C14.054,20.065 13.236,20.923 12,20.923
+ H12
+ Z
+ "
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#ffffff"/>
diff --git a/core/res/res/drawable/ic_thread_network.xml b/core/res/res/drawable/ic_thread_network.xml
new file mode 100644
index 0000000..1d7608f
--- /dev/null
+++ b/core/res/res/drawable/ic_thread_network.xml
@@ -0,0 +1,25 @@
+<!--
+ Copyright (C) 2024 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="960"
+ android:viewportHeight="960"
+ android:tint="?attr/colorControlNormal">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M476,880Q394,879 322,847.5Q250,816 196,761.5Q142,707 111,634.5Q80,562 80,480Q80,397 111.5,324Q143,251 197,197Q251,143 324,111.5Q397,80 480,80Q563,80 636,111.5Q709,143 763,197Q817,251 848.5,324Q880,397 880,480Q880,623 791.5,732.5Q703,842 563,871L563,480L607,480Q661,480 699.5,441.5Q738,403 738,349Q738,295 699.5,256.5Q661,218 607,218Q553,218 514.5,256.5Q476,295 476,349L476,393L345,393Q279,393 233,439Q187,485 187,551Q187,617 233,662.5Q279,708 345,708L345,621Q316,621 295,600.5Q274,580 274,551Q274,522 295,501Q316,480 345,480L476,480L476,880ZM563,393L563,349Q563,331 576,318Q589,305 607,305Q625,305 638,318Q651,331 651,349Q651,367 638,380Q625,393 607,393L563,393Z"/>
+</vector>
diff --git a/core/res/res/layout/miniresolver.xml b/core/res/res/layout/miniresolver.xml
index db0ea54..e60e0b0 100644
--- a/core/res/res/layout/miniresolver.xml
+++ b/core/res/res/layout/miniresolver.xml
@@ -33,7 +33,6 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alwaysShow="true"
- android:elevation="@dimen/resolver_elevation"
android:paddingTop="24dp"
android:paddingStart="@dimen/resolver_edge_margin"
android:paddingEnd="@dimen/resolver_edge_margin"
diff --git a/core/res/res/layout/side_fps_toast.xml b/core/res/res/layout/side_fps_toast.xml
index 96860b0..2c35c9b 100644
--- a/core/res/res/layout/side_fps_toast.xml
+++ b/core/res/res/layout/side_fps_toast.xml
@@ -18,28 +18,26 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:minWidth="350dp"
android:layout_gravity="center"
+ android:minWidth="350dp"
android:background="@color/side_fps_toast_background">
<TextView
- android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:layout_width="0dp"
+ android:layout_weight="6"
android:text="@string/fp_power_button_enrollment_title"
- android:singleLine="true"
- android:ellipsize="end"
android:textColor="@color/side_fps_text_color"
android:paddingLeft="20dp"/>
<Space
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_weight="1"/>
+ android:layout_width="5dp"
+ android:layout_height="match_parent" />
<Button
android:id="@+id/turn_off_screen"
- android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:layout_width="0dp"
+ android:layout_weight="3"
android:text="@string/fp_power_button_enrollment_button_text"
- android:paddingRight="20dp"
style="?android:attr/buttonBarNegativeButtonStyle"
android:textColor="@color/side_fps_button_color"
- android:maxLines="1"/>
+ />
</LinearLayout>
\ No newline at end of file
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 7f0e4c2..b65fc5f 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> na <xliff:g id="TIME_DELAY">{2}</xliff:g> sekondes"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nie aangestuur nie"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nie aangestuur nie"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Selnetwerksekuriteit"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Enkripsie, kennisgewings vir ongeënkripteerde netwerke"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"Toegang is tot toestel-ID verkry"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"’n Nabygeleë netwerk het om <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> jou toestel se unieke ID (IMSI of IMEI) aangeteken terwyl jou <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>-SIM gebruik is"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"’n Nabygeleë netwerk het om <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> jou toestel se unieke ID (IMSI of IMEI) aangeteken terwyl jou <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>-SIM gebruik is.\n\nDit beteken dat jou ligging, aktiwiteit of identiteit aangeteken is. Dit is ’n algemene praktyk, maar kan ’n kwessie wees vir mense wat bekommerd is oor privaatheid."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Verbind aan geënkripteerde netwerk <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>-SIM-verbinding is nou meer beveilig"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Verbind aan ongeënkripteerde netwerk"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Oproepe, boodskappe en data is tans meer kwesbaar terwyl jy jou <xliff:g id="NETWORK_NAME">%1$s</xliff:g>-SIM gebruik."</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Oproepe, boodskappe en data is tans meer kwesbaar terwyl jy jou <xliff:g id="NETWORK_NAME">%1$s</xliff:g>-SIM gebruik.\n\nJy sal nog ’n kennisgewing kry wanneer jou verbinding weer geënkripteer is."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Instellings vir selnetwerksekuriteit"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Meer inligting"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"Het dit"</string>
<string name="fcComplete" msgid="1080909484660507044">"Kenmerkkode klaar."</string>
<string name="fcError" msgid="5325116502080221346">"Verbindingsprobleem of ongeldige kenmerk-kode."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -371,8 +359,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Neem skermkiekie"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Kan \'n skermkiekie neem."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Voorskou, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"maak toe"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"deaktiveer of verander statusbalk"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Laat die app toe om die statusbalk te deaktiveer en stelselikone by te voeg of te verwyder."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"wees die statusbalk"</string>
@@ -2157,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Roetinemodus-inligtingkennisgewing"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Batterybespaarder is aangeskakel"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Verminder tans batterygebruik om batterylewe te verleng"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"Batterybespaarder is aan"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"Batterybespaarder is aangeskakel om batterylewe te verleng"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Batterybespaarder"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Batterybespaarder is afgeskakel"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Foon se battery het genoeg krag. Kenmerke is nie meer beperk nie."</string>
@@ -2231,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Skakel oor na werkapp?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Jou organisasie laat jou net toe om oproepe van werkapps af te maak"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Jou organisasie laat jou net toe om boodskappe van werkapps af te stuur"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Jy kan foonoproepe net van jou persoonlike Foon-app af maak. Oproepe wat met persoonlike Foon gemaak word, sal by jou persoonlike oproepgeskiedenis gevoeg word."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"Jy kan SMS-boodskappe net van jou persoonlike Boodskappe-app af stuur."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Gebruik persoonlike blaaier"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Gebruik werkblaaier"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Bel"</string>
@@ -2414,6 +2401,10 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Werk 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Toets"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Gemeenskaplik"</string>
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Werkprofiel"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Privaat ruimte"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Kloon"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Gemeenskaplik"</string>
<string name="redacted_notification_message" msgid="1520587845842228816">"Sensitiewe kennisgewinginhoud is versteek"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Appinhoud is weens sekuriteit van skermdeling verberg"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index cf6cd30..cef77b0 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>፡<xliff:g id="DIALING_NUMBER">{1}</xliff:g> ከ<xliff:g id="TIME_DELAY">{2}</xliff:g> ሰከንዶች በኋላ"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>፡አልተላለፈም"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>፡አልተላለፈም"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"የተንቀሳቃሽ ስልክ አውታረ መረብ ደኅንነት"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"ምስጠራ፣ ያልተመሰጠሩ የአውታረ መረቦች ማሳወቂያዎች"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"የመሣሪያ መታወቂያ ተደርሶበታል"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"<xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> ላይ በአቅራቢያዎ ያለ አውታረ መረብ የ<xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> ሲምዎን በመጠቀም ላይ ሳለ የመሣሪያዎን ልዩ መታወቂያ (IMSI ወይም IMEI) መዝግቧል"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"<xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> ላይ በአቅራቢያዎ ያለ አውታረ መረብ የ<xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> ሲምዎን በመጠቀም ላይ ሳለ የመሣሪያዎን ልዩ መታወቂያ (IMSI ወይም IMEI) መዝግቧል።\n\nይህ ማለት የእርስዎ አካባቢ፣ እንቅስቃሴ ወይም ማንነት ተመዝግቧል ማለት ነው። ይህ የተለመደ ተግባር ነው፣ ነገር ግን ስለግላዊነት ለሚጨነቁ ሰዎች ችግር ሊሆን ይችላል።"</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"ከተመሠጠረ አውታረ መረብ <xliff:g id="NETWORK_NAME">%1$s</xliff:g> ጋር ተገናኝቷል።"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"የ<xliff:g id="NETWORK_NAME">%1$s</xliff:g> ሲም ግንኙነት አሁን ደኅንነቱ ይበልጥ የተጠበቀ ነው።"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"ካልተመሠጠረ አውታረ መረብ ጋር ተገናኝቷል"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"የ<xliff:g id="NETWORK_NAME">%1$s</xliff:g> ሲምዎን በሚጠቀሙበት ጊዜ ጥሪዎች፣ መልዕክቶች እና ውሂብ በአሁኑ ጊዜ ይበልጥ ተጋላጭ ናቸው"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"የ<xliff:g id="NETWORK_NAME">%1$s</xliff:g> ሲምዎን በሚጠቀሙበት ጊዜ ጥሪዎች፣ መልዕክቶች እና ውሂብ በአሁኑ ጊዜ ይበልጥ ተጋላጭ ናቸው።\n\nግንኙነትዎ እንደገና ሲመሰጠር ሌላ ማሳወቂያ ይደርስዎታል።"</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"የተንቀሳቃሽ ስልክ አውታረ መረብ ደኅንነት ቅንብሮች"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"የበለጠ ለመረዳት"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"ገባኝ"</string>
<string name="fcComplete" msgid="1080909484660507044">" ኮድ ባህሪይ ተጠናቋል።"</string>
<string name="fcError" msgid="5325116502080221346">"የተያያዥ ችግር ወይም ትክከል ያልሆነኮድ ባህሪ።"</string>
<string name="httpErrorOk" msgid="6206751415788256357">"እሺ"</string>
@@ -2156,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"የዕለት ተዕለት ሁነታ መረጃ ማሳወቂያዎች"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"የባትሪ ኃይል ቆጣቢ በርቷል"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"የባትሪ ዕድሜን ለማራዘም የባትሪ አጠቃቀምን በመቀነስ ላይ"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"ባትሪ ቆጣቢ በርቷል"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"የባትሪ ዕድሜን ለማራዘም የባትሪ ኃይል ቆጣቢ በርቷል"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"ባትሪ ቆጣቢ"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"የባትሪ ቆጣቢ ጠፍቷል"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"ስልክ በቂ የባትሪ ኃይል አለው። ባህሪያት ከእንግዲህ የተገደቡ አይደሉም።"</string>
@@ -2230,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"ወደ የሥራ መተግበሪያ ይቀየር?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"ድርጅትዎ ከሥራ መተግበሪያዎች ብቻ ጥሪዎችን እንዲያደርጉ ይፈቅድልዎታል"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"ድርጅትዎ ከሥራ መተግበሪያዎች ብቻ መልዕክቶችን እንዲልኩ ይፈቅድልዎታል"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"የስልክ ጥሪዎችን ማድረግ የሚችሉት ከግል የስልክ መተግበሪያዎ ብቻ ነው። በግል ስልክ የተደረጉ ጥሪዎች ወደ የግል የጥሪ ታሪክዎ ይታከላሉ።"</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"የኤስኤምኤስ መልዕክቶችን ከግል የመልዕክት መተግበሪያዎ ብቻ ነው መላክ የሚችሉት።"</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"የግል አሳሽ ተጠቀም"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"የስራ አሳሽ ተጠቀም"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"ደውል"</string>
@@ -2413,8 +2401,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"ሥራ 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"ሙከራ"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"የጋራ"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"የሥራ መገለጫ"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"የግል ቦታ"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"አባዛ"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"የጋራ"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"አደገኛ የማሳወቂያ ይዘት ተደብቋል"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"ለደኅንነት ሲባል የመተግበሪያ ይዘት ከማያ ገጽ ማጋራት ተደብቋል"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"ከሳተላይት ጋር በራስ-ሰር ተገናኝቷል"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index dfaa285..2a5822a 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -157,31 +157,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> بعد <xliff:g id="TIME_DELAY">{2}</xliff:g> ثانية"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: لم تتم إعادة التوجيه"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: لم تتم إعادة التوجيه"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"أمان شبكة الجوّال"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"التشفير والإشعارات للشبكات غير المشفرة"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"تم الوصول إلى رقم تعريف الجهاز"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"في <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>، رصدت إحدى الشبكات المجاورة المعرّف الفريد لجهازك (رقم التعريف الدولي للمشترك في خدمات الجوّال (IMSI) أو IMEI) أثناء استخدام شريحة SIM لشبكة \"<xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>\""</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"في <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>، رصدت إحدى الشبكات المجاورة المعرّف الفريد لجهازك (رقم التعريف الدولي للمشترك في خدمات الجوّال (IMSI) أو IMEI) أثناء استخدام شريحة SIM لشبكة \"<xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>\".\n\nيعني هذا أنّه قد تم تسجيل موقعك الجغرافي أو نشاطك أو هويتك. وذلك من الممارسات الشائعة، ولكن قد يشعر بعض المستخدمين بالقلق بشأن خصوصيتهم."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"تم الاتصال بشبكة \"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>\" المشفَّرة"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"أصبح الاتصال باستخدام شريحة SIM لشبكة \"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>\" أكثر أمانًا الآن"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"تم الاتصال بشبكة غير مشفَّرة"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"المكالمات والرسائل والبيانات هي أكثر عرضة للاختراق في الوقت الحالي أثناء استخدام شريحة SIM لشبكة \"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>\""</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"المكالمات والرسائل والبيانات هي أكثر عرضة للاختراق في الوقت الحالي أثناء استخدام شريحة SIM لشبكة \"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>\".\n\nستتلقّى إشعارًا آخر عندما يتم تشفير اتصالك مرة أخرى."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"إعدادات أمان شبكة الجوّال"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"مزيد من المعلومات"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"حسنًا"</string>
<string name="fcComplete" msgid="1080909484660507044">"اكتمل رمز الميزة."</string>
<string name="fcError" msgid="5325116502080221346">"حدثت مشكلة بالاتصال أو أن رمز الميزة غير صحيح."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"حسنًا"</string>
@@ -1916,8 +1904,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"طلب إدخال رقم التعريف الشخصي قبل إزالة التثبيت"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"طلب إدخال نقش فتح القفل قبل إزالة التثبيت"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"طلب إدخال كلمة المرور قبل إزالة التثبيت"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"تم التثبيت من قِبل المشرف.\nانتقِل إلى الإعدادات للاطّلاع على الأذونات الممنوحة"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"تم التحديث بواسطة المشرف"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"تم الحذف بواسطة المشرف"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"حسنًا"</string>
@@ -2161,6 +2148,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"إشعار معلومات \"وضع سلسلة الإجراءات\""</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"تم تفعيل ميزة توفير شحن البطارية"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"يتم تقليل استخدام البطارية لإطالة عمرها."</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"تم تفعيل ميزة \"توفير شحن البطارية\""</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"تم تفعيل ميزة \"توفير شحن البطارية\" لإطالة عمر البطارية"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"توفير شحن البطارية"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"تم تفعيل ميزة \"توفير شحن البطارية\""</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"تم شحن الهاتف بدرجة كافية وتفعيل الميزات مرة أخرى"</string>
@@ -2235,10 +2224,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"هل تريد الانتقال إلى تطبيق العمل؟"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"تسمح لك مؤسستك بإجراء المكالمات من تطبيقات العمل فقط."</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"تسمح لك مؤسستك بإرسال الرسائل من تطبيقات العمل فقط."</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"يمكنك فقط إجراء مكالمات هاتفية من تطبيق الهاتف الشخصي، وستتم إضافة المكالمات التي أجريتها باستخدام هاتفك الشخصي إلى سجل المكالمات الشخصي."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"يمكنك فقط إرسال رسائل قصيرة SMS من تطبيق \"الرسائل\" الشخصي."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"استخدام المتصفّح الشخصي"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"استخدام متصفّح العمل"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"الاتصال"</string>
@@ -2418,6 +2405,10 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"ملف العمل 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"ملف شخصي تجريبي"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"ملف شخصي مشترك"</string>
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"ملف العمل"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"المساحة الخاصة"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"نسخة طبق الأصل"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"ملف شخصي مشترك"</string>
<string name="redacted_notification_message" msgid="1520587845842228816">"تم إخفاء المحتوى الحساس في الإشعار"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"تم إخفاء محتوى التطبيق بعد تفعيل ميزة \"مشاركة الشاشة\" للحفاظ على أمانك"</string>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index c695e86..6e0da54 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> ছেকেণ্ডৰ পাছত"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ফৰৱাৰ্ড কৰা নহ\'ল"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ফৰৱাৰ্ড কৰা নহ\'ল"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"ম’বাইল নেটৱৰ্কৰ সুৰক্ষা"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"এনক্ৰিপশ্বন, এনক্ৰিপ্ট নকৰা নেটৱৰ্কৰ বাবে জাননী"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"ডিভাইচৰ আইডি এক্সেছ কৰা হৈছে"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"<xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>ত, এটা নিকটৱৰ্তী নেটৱৰ্কে আপোনাৰ <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> ছিম ব্যৱহাৰ কৰাৰ সময়ত আপোনাৰ ডিভাইচৰ অদ্বিতীয় আইডি (IMSI বা IMEI) ৰেকৰ্ড কৰিছে"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"<xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>ত, এটা নিকটৱৰ্তী নেটৱৰ্কে আপোনাৰ <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> ছিম ব্যৱহাৰ কৰাৰ সময়ত আপোনাৰ ডিভাইচৰ অদ্বিতীয় আইডি (IMSI বা IMEI) ৰেকৰ্ড কৰিছে।\n\n ইয়াৰ অৰ্থ হৈছে যে আপোনাৰ অৱস্থান, কাৰ্যকলাপ বা পৰিচয়ৰ লগ তৈয়াৰ কৰা হৈছে। এইটো সাধাৰণভাৱে কৰা অনুশীলন যদিও গোপনীয়তাক সম্পৰ্কে চিন্তিত লোকসকলৰ বাবে ই এটা সমস্যা হ’ব পাৰে।"</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"এনক্ৰিপ্ট কৰা নেটৱৰ্ক <xliff:g id="NETWORK_NAME">%1$s</xliff:g>ৰ সৈতে সংযুক্ত কৰা আছে"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> ছিমৰ সংযোগ এতিয়া অধিক সুৰক্ষিত"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"এনক্ৰিপ্ট নকৰা নেটৱৰ্কৰ সৈতে সংযুক্ত কৰা আছে"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"আপোনাৰ <xliff:g id="NETWORK_NAME">%1$s</xliff:g> ছিম ব্যৱহাৰ কৰাৰ সময়ত কল, বাৰ্তা আৰু ডেটা বৰ্তমানে অধিক অসুৰক্ষিত হোৱাৰ বিপদাশংকা আছে"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"আপোনাৰ <xliff:g id="NETWORK_NAME">%1$s</xliff:g> ছিম ব্যৱহাৰ কৰাৰ সময়ত কল, বাৰ্তা আৰু ডেটা বৰ্তমানে অধিক অসুৰক্ষিত হোৱাৰ বিপদাশংকা আছে।\n\nযেতিয়া আপোনাৰ সংযোগ পুনৰ এনক্ৰিপ্ট কৰা হয়, তেতিয়া আপুনি আন এটা জাননী পাব।"</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"ম’বাইল নেটৱৰ্কৰ সুৰক্ষাৰ ছেটিং"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"অধিক জানক"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"বুজি পালোঁ"</string>
<string name="fcComplete" msgid="1080909484660507044">"সুবিধাৰ ক\'ড সম্পূর্ণ হ’ল।"</string>
<string name="fcError" msgid="5325116502080221346">"সংযোগত সমস্যা হৈছে বা সুবিধাৰ ক\'ড অমান্য।"</string>
<string name="httpErrorOk" msgid="6206751415788256357">"ঠিক আছে"</string>
@@ -2156,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"ৰুটিন ম’ডৰ তথ্য জাননী"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"বেটাৰী সঞ্চয়কাৰী অন কৰা হৈছে"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"বেটাৰীৰ জীৱনকাল বৃদ্ধি কৰিবলৈ বেটাৰীৰ ব্যৱহাৰ কমোৱা হৈছে"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"বেটাৰী সঞ্চয়কাৰী অন কৰা হৈছে"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"বেটাৰীৰ জীৱনকাল বৃদ্ধি কৰিবলৈ বেটাৰী সঞ্চয়কাৰী অন কৰা হৈছে"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"বেটাৰী সঞ্চয়কাৰী"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"বেটাৰী সঞ্চয়কাৰী অফ কৰা হ’ল"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"ফ\'নটোত পর্যাপ্ত পৰিমাণে চার্জ আছে। সুবিধাবোৰ আৰু সীমাবদ্ধ কৰা নাই।"</string>
@@ -2230,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"ইয়াৰ সলনি কাম সম্পৰ্কীয় এপ্ ব্যৱহাৰ কৰিবনে?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"আপোনাৰ প্ৰতিষ্ঠানে আপোনাক কেৱল কাম সম্পৰ্কীয় এপ্সমূহৰ পৰা কল কৰিবলৈ অনুমতি দিয়ে"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"আপোনাৰ প্ৰতিষ্ঠানে আপোনাক কেৱল কাম সম্পৰ্কীয় এপ্সমূহৰ পৰা বাৰ্তা পঠিওৱাৰ অনুমতি দিয়ে"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"আপুনি আপোনাৰ ব্যক্তিগত Phone এপৰ পৰা কেৱল ফ’ন কল কৰিব পাৰিব। ব্যক্তিগত Phone এপৰ জৰিয়তে কৰা কল আপোনাৰ ব্যক্তিগত কলৰ ইতিহাসত যোগ দিয়া হ’ব।"</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"আপুনি আপোনাৰ ব্যক্তিগত Messages এপৰ পৰা কেৱল এছএমএছ বাৰ্তা পঠিয়াব পাৰিব।"</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"ব্যক্তিগত ব্ৰাউজাৰ ব্যৱহাৰ কৰক"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"কৰ্মস্থানৰ ব্ৰাউজাৰ ব্যৱহাৰ কৰক"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"কল কৰক"</string>
@@ -2413,8 +2401,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"কৰ্মস্থান ৩"</string>
<string name="profile_label_test" msgid="9168641926186071947">"পৰীক্ষা"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"শ্বেয়াৰ কৰা"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"কৰ্মস্থানৰ প্ৰ’ফাইল"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"প্ৰাইভেট স্পে’চ"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"ক্ল’ন"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"সম্প্ৰদায়ৰ সৈতে জড়িত"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"সংবেদনশীল জাননী লুকুওৱা হৈছে"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"সুৰক্ষাৰ বাবে এপৰ সমল স্ক্ৰীণ শ্বেয়াৰ কৰাৰ পৰা লুকুৱাই ৰখা হৈছে"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"উপগ্ৰহৰ সৈতে স্বয়ংক্ৰিয়ভাৱে সংযুক্ত হৈছে"</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index c110e3e..a3d4423 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> saniyə sonra"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Yönləndirilmədi"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Yönləndirilmədi"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Mobil şəbəkə güvənliyi"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Şifrələmə, şifrələnməmiş şəbəkələr üçün bildirişlər"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"Cihaz ID-nə giriş edildi"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"<xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> radələrində <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> SIM-i istifadə edərkən yaxınlıqdakı şəbəkə cihazın unikal ID məlumatını (IMSI və ya IMEI) qeydə alıb"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"<xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> radələrində <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> SIM-i istifadə edərkən yaxınlıqdakı şəbəkə cihazın unikal ID məlumatını (IMSI və ya IMEI) qeydə alıb.\n\nBu o deməkdir ki, məkan, fəaliyyət və ya kimliyiniz qeydə alınıb. Bu, adi haldır, lakin məxfilik barədə narahat olan insanlar üçün problem ola bilər."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> adlı şifrələnmiş şəbəkəyə qoşulub"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM bağlantısı artıq daha güvənlidir"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Şifrələnməmiş şəbəkəyə qoşulub"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Hazırda <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM-dən istifadə edərkən zəng, mesaj və data güvənliyi daha aşağıdır"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Hazırda <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM-dən istifadə edərkən zəng, mesaj və data güvənliyi daha aşağıdır.\n\nBağlantı yenidən şifrələndikdə başqa bildiriş alacaqsınız."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Mobil şəbəkə güvənliyi ayarları"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Ətraflı məlumat"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"Anladım"</string>
<string name="fcComplete" msgid="1080909484660507044">"Özəllik kodu tamamlandı."</string>
<string name="fcError" msgid="5325116502080221346">"Əlaqə problemi və ya yanlış funksiya kodu."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -371,8 +359,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ekran şəkli çəkin"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Ekran şəkli çəkilə bilər."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Önizləmə, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"kənarlaşdırın"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"status panelini deaktivləşdir və ya dəyişdir"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Tətbiqə status panelini deaktiv etməyə və ya sistem ikonalarını əlavə etmək və ya silmək imkanı verir."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"status paneli edin"</string>
@@ -2157,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Rejim üçün məlumat bildirişi"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Enerjiyə Qənaət aktivdir"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Batareyanın ömrünü uzatmaq üçün batareyadan istifadəni azaldın"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"Enerjiyə Qənaət yanılıdır"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"Batareya istifadəsini artırmaq üçün Enerjiyə Qənaət yandırıldı"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Enerjiyə qənaət"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Enerjiyə qənaət deaktivdir"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Telefonun kifayət qədər enerjisi var. Funksiyalar artıq məhdud deyil."</string>
@@ -2231,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"İş tətbiqinə dəyişilsin?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Təşkilat yalnız iş tətbiqindən zəng etməyə icazə verir"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Təşkilat yalnız iş tətbiqindən mesaj göndərməyə icazə verir"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Yalnız şəxsi Telefon tətbiqindən telefon zəngləri edə bilərsiniz. Şəxsi Telefon ilə edilmiş zənglər şəxsi zəng tarixçənizə əlavə ediləcək."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"Yalnız şəxsi Mesajlaşma tətbiqindən SMS mesajları göndərə bilərsiniz."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Şəxsi brauzerdən istifadə edin"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"İş brauzerindən istifadə edin"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Zəng edin"</string>
@@ -2414,6 +2401,10 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"İş 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Kommunal"</string>
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"İş profili"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Məxfi sahə"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Klon"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Kommunal"</string>
<string name="redacted_notification_message" msgid="1520587845842228816">"Həssas bildiriş kontenti gizlədildi"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Güvənlik üçün tətbiq kontenti ekran paylaşımından gizlədildi"</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 2977bfb..fff999a 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -154,31 +154,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> nakon <xliff:g id="TIME_DELAY">{2}</xliff:g> sekunde/i"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nije prosleđeno"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nije prosleđeno"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Bezbednost na mobilnoj mreži"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Šifrovanje, obaveštenja za nešifrovane mreže"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"Pristupljeno je ID-u uređaja"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"Mreža u blizini je u <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> evidentirala jedinstveni ID vašeg uređaja (IMSI ili IMEI) dok ste koristili <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> SIM"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"Mreža u blizini je u <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> evidentirala jedinstveni ID vašeg uređaja (IMSI ili IMEI) dok ste koristili <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> SIM.\n\nTo znači da je evidentirala vašu lokaciju, aktivnost i identitet. To je uobičajena praksa, ali može da bude problem ljudima koji su zabrinuti za privatnost."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Povezani ste na šifrovanu mrežu <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"Veza <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM-a je sada bezbednija"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Povezani ste na šifrovanu mrežu"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Pozivi, poruke i podaci su trenutno ranjiviji dok koristite <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Pozivi, poruke i podaci su trenutno ranjiviji dok koristite <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM.\n\nKada veza ponovo bude šifrovana, poslaćemo vam drugo obaveštenje."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Podešavanja bezbednosti na mobilnoj mreži"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Saznajte više"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"Važi"</string>
<string name="fcComplete" msgid="1080909484660507044">"Kôd funkcije je izvršen."</string>
<string name="fcError" msgid="5325116502080221346">"Problemi sa vezom ili nevažeći kôd funkcije."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"Potvrdi"</string>
@@ -339,7 +327,7 @@
<string name="permgroupdesc_storage" msgid="5378659041354582769">"pristup fajlovima na uređaju"</string>
<string name="permgrouplab_readMediaAural" msgid="1858331312624942053">"Muzika i zvuk"</string>
<string name="permgroupdesc_readMediaAural" msgid="7565467343667089595">"pristup muzici i audio sadržaju na uređaju"</string>
- <string name="permgrouplab_readMediaVisual" msgid="4724874717811908660">"Slike i video snimci"</string>
+ <string name="permgrouplab_readMediaVisual" msgid="4724874717811908660">"Slike i videi"</string>
<string name="permgroupdesc_readMediaVisual" msgid="4080463241903508688">"pristup slikama i videima na uređaju"</string>
<string name="permgrouplab_microphone" msgid="2480597427667420076">"Mikrofon"</string>
<string name="permgroupdesc_microphone" msgid="1047786732792487722">"snima zvuk"</string>
@@ -2157,6 +2145,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Obaveštenje o informacijama Rutinskog režima"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Ušteda baterije je uključena"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Smanjuje se potrošnja baterije da bi se produžilo njeno trajanje"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"Ušteda baterije je uključena"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"Ušteda baterije je uključena da bi se produžilo trajanje baterije"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Ušteda baterije"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Ušteda baterije je isključena"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Baterija telefona je dovoljno napunjena. Funkcije više nisu ograničene."</string>
@@ -2231,10 +2221,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Želite da prebacite na poslovnu aplikaciju?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Vaša organizacija dozvoljava pozivanje samo iz poslovnih aplikacija"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Vaša organizacija dozvoljava slanje poruka samo iz poslovnih aplikacija"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Telefonske pozive možete da upućujete samo iz lične aplikacije Telefon. Pozivi upućeni pomoću lične aplikacije Telefon dodaju se u ličnu istoriju poziva."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"SMS poruke možete da šaljete samo iz lične aplikacije Messages."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Koristi lični pregledač"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Koristi poslovni pregledač"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Pozovi"</string>
@@ -2414,8 +2402,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Posao 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Zajedničko"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Poslovni profil"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Privatan prostor"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Klonirano"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Zajedničko"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Osetljiv sadržaj obaveštenja je skriven"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Sadržaj aplikacije je skriven za deljenje sadržaja ekrana zbog bezbednosti"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Automatski povezano sa satelitom"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 0a009a2..19ca1c4 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -155,31 +155,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> праз <xliff:g id="TIME_DELAY">{2}</xliff:g> с."</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: не пераадрасоўваецца"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: не пераадрасоўваецца"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Сеткавая бяспека"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Шыфраванне, апавяшчэнні для незашыфраваных сетак"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"Атрыманы доступ да ідэнтыфікатара прылады"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"У <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> у сетцы паблізу быў запісаны ўнікальны ідэнтыфікатар вашай прылады (IMSI або IMEI) пры выкарыстанні SIM-карты <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"У <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> у сетцы паблізу быў запісаны ўнікальны ідэнтыфікатар вашай прылады (IMSI або IMEI) пры выкарыстанні SIM-карты <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>.\n\nГэта азначае, што даныя пра ваша месцазнаходжанне, дзеянні або асобу былі зарэгістраваны. Гэта звычайная практыка, але можа быць праблемай для людзей, якія турбуюцца аб прыватнасці."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Падключана да зашыфраванай сеткі <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"Цяпер падключэнне да SIM-карты <xliff:g id="NETWORK_NAME">%1$s</xliff:g> стала больш бяспечным"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Падключана да зашыфраванай сеткі"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Зараз выклікі, паведамленні і даныя менш абаронены пры выкарыстанні SIM-карты <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Зараз выклікі, паведамленні і даныя менш абаронены пры выкарыстанні SIM-карты <xliff:g id="NETWORK_NAME">%1$s</xliff:g>.\n\nКалі падключэнне будзе зноў зашыфравана, вы атрымаеце апавяшчэнне."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Налады сеткавай бяспекі"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Даведацца больш"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"ОК"</string>
<string name="fcComplete" msgid="1080909484660507044">"Код аб\'екта завершаны."</string>
<string name="fcError" msgid="5325116502080221346">"Праблема падлучэння ці няправільны код функцыі."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"ОК"</string>
@@ -373,8 +361,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Зрабіць здымак экрана"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Можна зрабіць здымак экрана."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Перадпрагляд, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"закрыць"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"адключаць ці змяняць радок стану"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Дазваляе прыкладанням адключаць радок стану або дадаваць і выдаляць сістэмныя значкі."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"быць панэллю стану"</string>
@@ -2159,6 +2146,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Апавяшчэнне з інфармацыяй пра ўсталяваны рэжым"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Рэжым энергазберажэння ўключаны"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Абмежаванне выкарыстання зараду для падаўжэння часу працы ад акумулятара"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"Рэжым энергазберажэння ўключаны"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"Каб падоўжыць час працы ад акумулятара, уключаны рэжым энергазберажэння"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Рэжым энергазберажэння"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Рэжым эканоміі зараду выключаны"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"У тэлефона дастатковы ўзровень зараду. Функцыі больш не абмежаваны."</string>
@@ -2233,10 +2222,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Пераключыцца на працоўную праграму?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Ваша арганізацыя дазваляе рабіць выклікі толькі з працоўных праграм"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Ваша арганізацыя дазваляе адпраўляць паведамленні толькі з працоўных праграм"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Вы можаце ажыццяўляць выклікі толькі з асабістай праграмы \"Тэлефон\". Зробленыя выклікі будуць дададзены ў гісторыю выклікаў."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"Вы можаце адпраўляць SMS-паведамленні толькі з асабістай праграмы \"Паведамленні\"."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Скарыстаць асабісты браўзер"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Скарыстаць працоўны браўзер"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Выклікаць"</string>
@@ -2416,8 +2403,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Працоўны 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Тэставы"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Супольны"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Працоўны профіль"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Прыватная прастора"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Клон"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Супольны"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Канфідэнцыяльнае змесціва ў апавяшчэннях схавана"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Змесціва праграмы выключана з абагульвання экрана ў мэтах бяспекі"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Аўтаматычна падключана да сістэм спадарожнікавай сувязі"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 134881d..2f1ecdb 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> след <xliff:g id="TIME_DELAY">{2}</xliff:g> секунди"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Не е пренасочено"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Не е пренасочено"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Сигурност на мобилната мрежа"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Шифроване, известия за нешифровани мрежи"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"Осъществен е достъп до ID на устройството"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"В <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> близка до вас мрежа записа уникалния идентификатор на устройството ви (IMSI или IMEI), докато използвахте SIM картата си от <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"В <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> близка до вас мрежа записа уникалния идентификатор на устройството ви (IMSI или IMEI), докато използвахте SIM картата си от <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>.\n\nТова означава, че местоположението, активността или самоличността ви са регистрирани. Това е често срещана практика, която обаче може да представлява проблем за хората, които се тревожат за поверителността си."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Установена е връзка с шифрованата мрежа <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"Връзката със SIM картата от <xliff:g id="NETWORK_NAME">%1$s</xliff:g> вече е по-сигурна"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Установена е връзка с нешифрована мрежа"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Понастоящем обажданията, съобщенията и данните са по-уязвими, докато използвате SIM картата си от <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Понастоящем обажданията, съобщенията и данните са по-уязвими, докато използвате SIM картата си от <xliff:g id="NETWORK_NAME">%1$s</xliff:g>.\n\nСлед като връзката ви бъде шифрована отново, ще получите друго известие."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Настройки за сигурност на мобилната мрежа"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Научете повече"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"Разбрах"</string>
<string name="fcComplete" msgid="1080909484660507044">"Кодът за функцията се изпълни."</string>
<string name="fcError" msgid="5325116502080221346">"Има проблем с връзката или кодът за функцията е невалиден."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -2156,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Известие с информация за режима на поредица"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Режимът за запазване на батерията е включен"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Използването на батерията се намалява с цел удължаване на живота ѝ"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"Режимът за запазване на батерията е включен"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"Режимът за запазване на батерията е включен с цел удължаване на живота ѝ"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Режим за запазване на батерията"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Режимът за запазване на батерията е изключен"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Батерията на телефона има достатъчно заряд. Функциите вече не са ограничени."</string>
@@ -2230,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Искате ли да превключите към служебното приложение?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Организацията ви разрешава да извършвате обаждания само от служебни приложения"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Организацията ви разрешава да изпращате съобщения само от служебни приложения"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Можете да извършвате телефонни обаждания само от приложението Телефон в личния си потребителски профил. Обажданията, които извършите с това приложение, ще бъдат добавени към личната ви история на обажданията."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"Можете да изпращате SMS съобщения само от приложението Messages в личния си потребителски профил."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Използване на личния браузър"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Използване на служебния браузър"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Обаждане"</string>
@@ -2413,6 +2401,10 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Служебни 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Тестване"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Общи"</string>
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Служебен потребителски профил"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Частно пространство"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Клониране"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Общи"</string>
<string name="redacted_notification_message" msgid="1520587845842228816">"Деликатното съдържание в известието е скрито"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Съдържанието на приложението е скрито от функцията за споделяне на екрана от съображения за сигурност"</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index 866f71f..f1ebfb0 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> সেকেন্ড পরে"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ফরওয়ার্ড করা হয়নি"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ফরওয়ার্ড করা হয়নি"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"মোবাইল নেটওয়ার্ক সুরক্ষা"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"এনক্রিপশন, এনক্রিপটেড নয় এমন নেটওয়ার্কের জন্য বিজ্ঞপ্তি"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"ডিভাইস আইডি অ্যাক্সেস করা হয়েছে"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"আপনার <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> সিম কার্ড ব্যবহার করে <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>-এ, আশেপাশের নেটওয়ার্ক আপনার ডিভাইসের অনন্য আইডি (IMSI অথবা IMEI) রেকর্ড করেছে"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"আপনার <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> সিম কার্ড ব্যবহার করে <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>-এ, আশেপাশের নেটওয়ার্ক আপনার ডিভাইসের অনন্য আইডি (IMSI অথবা IMEI) রেকর্ড করেছে।\n\nএটির মানে হল আপনার লোকেশন, অ্যাক্টিভিটি বা পরিচিতি লগ-ইন করা হয়েছে। এটি সাধারণ পদ্ধতি কিন্তু সেইসব লোকজনের জন্য সমস্যা হতে পারে যারা নিজেদের গোপনীয়তা নিয়ে উদ্বেগে থাকেন।"</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> এনক্রিপটেড নেটওয়ার্কের সাথে কানেক্ট করা রয়েছে"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"এখন <xliff:g id="NETWORK_NAME">%1$s</xliff:g> সিম কার্ডের কানেকশন আরও সুরক্ষিত"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"এনক্রিপটেড নয় এমন নেটওয়ার্কের সাথে কানেক্ট করা রয়েছে"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> সিম কার্ড ব্যবহার করার সময়, কল, মেসেজ এবং ডেটা হ্যাক হওয়ার সম্ভাবনা বর্তমানে আরও বেশি রয়েছে"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> সিম কার্ড ব্যবহার করার সময়, কল, মেসেজ এবং ডেটা হ্যাক হওয়ার সম্ভাবনা বর্তমানে আরও বেশি রয়েছে।\n\nআপনার কানেকশন আবার এনক্রিপ্ট করা হলে, আপনি অন্য একটি বিজ্ঞপ্তি পাবেন।"</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"মোবাইল নেটওয়ার্ক সুরক্ষা সেটিংস"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"আরও জানুন"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"বুঝেছি"</string>
<string name="fcComplete" msgid="1080909484660507044">"বৈশিষ্ট্যসূচক কোড সম্পূর্ণ হয়েছে৷"</string>
<string name="fcError" msgid="5325116502080221346">"সংযোগ সমস্যা বা অবৈধ বৈশিষ্ট্যসূচক কোড৷"</string>
<string name="httpErrorOk" msgid="6206751415788256357">"ঠিক আছে"</string>
@@ -371,8 +359,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"স্ক্রিনশট নিন"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ডিসপ্লের একটি স্ক্রিনশট নিতে পারেন।"</string>
<string name="dream_preview_title" msgid="5570751491996100804">"প্রিভিউ, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"বাতিল করুন"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"স্ট্যাটাস বার নিষ্ক্রিয় অথবা সংশোধন করে"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"অ্যাপ্লিকেশনকে স্ট্যাটাস বার অক্ষম করতে এবং সিস্টেম আইকনগুলি সরাতে দেয়৷"</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"স্থিতি দন্ডে থাকুন"</string>
@@ -1224,7 +1211,7 @@
<string name="rating_label" msgid="1837085249662154601">"{rating,plural, =1{{max}টির মধ্যে একটি স্টার}one{#টির মধ্যে {max}টি স্টার}other{#টির মধ্যে {max}টি স্টার}}"</string>
<string name="in_progress" msgid="2149208189184319441">"কাজ চলছে"</string>
<string name="whichApplication" msgid="5432266899591255759">"এটি ব্যবহার করে ক্রিয়াকলাপ সম্পূর্ণ করুন"</string>
- <string name="whichApplicationNamed" msgid="6969946041713975681">"%1$s ব্যবহার করে ক্রিয়াকলাপ সম্পূর্ণ করুন"</string>
+ <string name="whichApplicationNamed" msgid="6969946041713975681">"%1$s ব্যবহার করে কাজটি করুন"</string>
<string name="whichApplicationLabel" msgid="7852182961472531728">"ক্রিয়াকলাপ সম্পূর্ণ করুন"</string>
<string name="whichViewApplication" msgid="5733194231473132945">"এর মাধ্যমে খুলুন"</string>
<string name="whichViewApplicationNamed" msgid="415164730629690105">"%1$s দিয়ে খুলুন"</string>
@@ -1250,7 +1237,7 @@
<string name="whichImageCaptureApplicationNamed" msgid="8820702441847612202">"%1$s দিয়ে ছবি তুলুন"</string>
<string name="whichImageCaptureApplicationLabel" msgid="6505433734824988277">"ছবি তুলুন"</string>
<string name="alwaysUse" msgid="3153558199076112903">"এই ক্রিয়াটির জন্য এটিকে ডিফল্টরুপে ব্যবহার করুন৷"</string>
- <string name="use_a_different_app" msgid="4987790276170972776">"আলাদা কোনো অ্যাপ্লিকেশান ব্যবহার করুন"</string>
+ <string name="use_a_different_app" msgid="4987790276170972776">"আলাদা কোনও অ্যাপ ব্যবহার করুন"</string>
<string name="clearDefaultHintMsg" msgid="1325866337702524936">"সিস্টেম সেটিংস > অ্যাপ্স > ডাউনলোড করাগুলি এ গিয়ে ডিফল্ট সরিয়ে দিন৷"</string>
<string name="chooseActivity" msgid="8563390197659779956">"একটি ক্রিয়া বেছে নিন"</string>
<string name="chooseUsbActivity" msgid="2096269989990986612">"USB ডিভাইসটির জন্য একটি অ্যাপ্লিকেশান বেছে নিন"</string>
@@ -2157,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"রুটিন মোডের তথ্য সংক্রান্ত বিজ্ঞপ্তি"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"\'ব্যাটারি সেভার\' ফিচার চালু করা হয়েছে"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"ব্যাটারির আয়ু বাড়াতে ব্যাটারির ব্যবহার কমানো হচ্ছে"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"\'ব্যাটারি সেভার\' চালু করা হয়েছে"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"ব্যাটারির আয়ু বাড়াতে \'ব্যাটারি সেভার\' চালু করা হয়েছে"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"ব্যাটারি সেভার"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"ব্যাটারি সেভার বন্ধ করা আছে"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"ফোনের ব্যাটারিতে যথেষ্ট চার্জ আছে। ফিচারগুলির উপর আর বিধিনিষেধ নেই।"</string>
@@ -2231,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"অফিসের অ্যাপে পরিবর্তন করবেন?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"আপনার সংস্থা শুধু অফিসের অ্যাপ থেকেই আপনাকে কল করার অনুমতি দেয়"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"আপনার সংস্থা শুধু অফিসের অ্যাপ থেকেই আপনাকে মেসেজ পাঠানোর অনুমতি দেয়"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"আপনার ব্যক্তিগত ফোন অ্যাপ থেকে শুধুমাত্র ফোন কল করতে পারবেন। ব্যক্তিগত ফোন থেকে করা কল আপনার ব্যক্তিগত কলের ইতিহাসে যোগ করা হবে।"</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"আপনার ব্যক্তিগত Messages অ্যাপ থেকে শুধুমাত্র এসএমএস মেসেজ পাঠাতে পারবেন।"</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"ব্যক্তিগত ব্রাউজার ব্যবহার করুন"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"অফিস ব্রাউজার ব্যবহার করুন"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"কল করুন"</string>
@@ -2414,8 +2401,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"৩য় অফিস"</string>
<string name="profile_label_test" msgid="9168641926186071947">"পরীক্ষা"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"কমিউনাল"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"অফিস প্রোফাইল"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"প্রাইভেট স্পেস"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"ক্লোন"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"কমিউনাল"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"সংবেদনশীল বিজ্ঞপ্তির কন্টেন্ট লুকানো আছে"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"নিরাপত্তার জন্য স্ক্রিন শেয়ার করা থেকে লুকানো অ্যাপের কন্টেন্ট"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"স্যাটেলাইটের সাথে অটোমেটিক কানেক্ট করা হয়েছে"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index d641d5a..1212af9 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -154,31 +154,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> za <xliff:g id="TIME_DELAY">{2}</xliff:g> sekundi"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nije proslijeđen"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Poziv nije proslijeđen"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Sigurnost mobilne mreže"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Šifriranje, obavještenja za nešifrirane mreže"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"Pristupljeno je ID-u uređaja"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"U <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> mreža u blizini je zabilježila jedinstveni ID uređaja (IMSI ili IMEI) koristeći SIM mreže <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"U <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> mreža u blizini je zabilježila jedinstveni ID uređaja (IMSI ili IMEI) koristeći SIM mreže <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>.\n\nOvo znači da su vaša lokacija, aktivnost ili identitet zabilježeni. Ovo je uobičajena praksa, ali može predstavljati problem za osobe zabrinute za privatnost."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Povezani ste sa šifriranom mrežom <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"Povezivanje SIM-a s mrežom <xliff:g id="NETWORK_NAME">%1$s</xliff:g> je sada sigurnije"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Povezani ste s nešifriranom mrežom"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Pozivi, poruke i podaci su trenutno osjetljiviji dok koristite SIM mreže <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Pozivi, poruke i podaci su trenutno osjetljiviji dok koristite SIM mreže <xliff:g id="NETWORK_NAME">%1$s</xliff:g>.\n\nKada veza ponovo bude šifrirana, primit ćete još jedno obavještenje."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Postavke sigurnosti mobilne mreže"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Saznajte više"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"Razumijem"</string>
<string name="fcComplete" msgid="1080909484660507044">"Kôd za posebne usluge potpun."</string>
<string name="fcError" msgid="5325116502080221346">"Problem sa povezivanjem ili nevažeći kôd za posebne usluge."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"Uredu"</string>
@@ -372,8 +360,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"praviti snimke ekrana"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Može napraviti snimak ekrana."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Pregled, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"odbacivanje"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"onemogućavanje ili mijenjanje statusne trake"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Dozvoljava aplikaciji onemogućavanje statusne trake ili dodavanje i uklanjanje sistemskih ikona."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"funkcioniranje u vidu statusne trake"</string>
@@ -2158,6 +2145,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Obavještenje za informacije Rutinskog načina"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Ušteda baterije je uključena"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Smanjena je potrošnja baterije da se produži vijek trajanja baterije"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"Ušteda baterije je uključena"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"Ušteda baterije je uključena radi produženja vijeka trajanja baterije"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Ušteda baterije"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Ušteda baterije je isključena"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Telefon se dovoljno napunio. Funkcije nisu više ograničene."</string>
@@ -2232,10 +2221,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Prebaciti na poslovnu aplikaciju?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Vaša organizacija vam dozvoljava da upućujete pozive samo iz poslovnih aplikacija"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Vaša organizacija vam dozvoljava da šaljete poruke samo iz poslovnih aplikacija"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Telefonske pozive možete upućivati samo iz lične aplikacije Telefon. Pozivi upućeni ličnim telefonom će se dodavati u vašu ličnu historiju poziva."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"SMS poruke možete slati samo iz lične aplikacije Messages."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Koristi lični preglednik"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Koristi poslovni preglednik"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Pozovi"</string>
@@ -2415,8 +2402,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"3. poslovno"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Testno"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Opće"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Radni profil"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Privatni prostor"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Klon"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Opće"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Sakriven je osjetljiv sadržaj obavještenja"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Sadržaj aplikacije je sakriven od dijeljenja ekrana radi sigurnosti"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Automatski je povezano sa satelitom"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 79afa25..f244779 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -154,31 +154,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> després de <xliff:g id="TIME_DELAY">{2}</xliff:g> segons"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: no s\'ha desviat"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: no s\'ha desviat"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Seguretat de xarxes mòbils"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Encriptació, notificacions de xarxes sense encriptació"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"S\'ha accedit a l\'identificador de dispositiu"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"A les <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, una xarxa propera ha registrat l\'identificador únic del teu dispositiu (IMSI or IMEI) mentre s\'utilitzava la SIM de <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"A les <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, una xarxa propera ha registrat l\'identificador únic del teu dispositiu (IMSI or IMEI) mentre s\'utilitzava la SIM de <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>.\n\nAixò vol dir que s\'han registrat la teva ubicació, activitat o identitat. Tot i ser una pràctica habitual, pot suposar un problema per a aquelles persones preocupades per la privadesa."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"T\'has connectat a la xarxa encriptada <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"La connexió SIM de <xliff:g id="NETWORK_NAME">%1$s</xliff:g> ara és més segura"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"T\'has connectat a una xarxa sense encriptació"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Les trucades, els missatges i les dades ara són més vulnerables amb la SIM de <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Les trucades, els missatges i les dades ara són més vulnerables amb la SIM de <xliff:g id="NETWORK_NAME">%1$s</xliff:g>.\n\nRebràs una altra notificació quan la connexió torni a estar encriptada."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Configuració de seguretat de xarxes mòbils"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Més informació"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"Entesos"</string>
<string name="fcComplete" msgid="1080909484660507044">"Codi de funció completat."</string>
<string name="fcError" msgid="5325116502080221346">"Problema de connexió o codi de funció no vàlid."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"D\'acord"</string>
@@ -372,8 +360,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Fer una captura de pantalla"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Pot fer una captura de la pantalla."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Previsualitza, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"ignora"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"desactivar o modificar la barra d\'estat"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Permet que l\'aplicació desactivi la barra d\'estat o afegeixi i elimini icones del sistema."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"aparèixer a la barra d\'estat"</string>
@@ -2158,6 +2145,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Notificació d\'informació del mode de rutina"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Estalvi de bateria s\'ha activat"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"S\'està reduint l\'ús de la bateria per allargar-ne la durada"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"La funció Estalvi de bateria està activada"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"S\'ha activat la funció Estalvi de bateria per allargar la durada de la bateria"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Estalvi de bateria"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"L\'estalvi de bateria s\'ha desactivat"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"El telèfon té prou bateria. Les funcions ja no estan restringides."</string>
@@ -2232,10 +2221,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Vols canviar a l\'aplicació de treball?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"La teva organització només et permet fer trucades des d\'aplicacions de treball"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"La teva organització només et permet enviar missatges des d\'aplicacions de treball"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Només pots fer trucades des de la teva aplicació Telèfon personal. Les trucades que facis amb aquesta aplicació s\'afegiran al teu historial de trucades personal."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"Només pots enviar missatges SMS des de la teva aplicació Missatges personal."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Utilitza el navegador personal"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Utilitza el navegador de treball"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Truca"</string>
@@ -2415,8 +2402,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Treball 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Prova"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Compartit"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Perfil de treball"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Espai privat"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Clon"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Comunitari"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"S\'ha amagat contingut sensible de les notificacions"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Contingut de l\'aplicació amagat de la compartició de pantalla per motius de seguretat"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"S\'ha connectat automàticament a un satèl·lit"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index d6565c1..6b04267 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -155,31 +155,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> po <xliff:g id="TIME_DELAY">{2}</xliff:g> sek."</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nepřesměrováno"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nepřesměrováno"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Zabezpečení mobilních sítí"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Šifrování, oznámení o nezašifrovaných sítích"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"Přístup k ID zařízení"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"V <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> zaznamenala síť v okolí při použití SIM karty <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> jedinečný identifikátor vašeho zařízení (IMSI nebo IMEI)"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"V <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> zaznamenala síť v okolí při použití SIM karty <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> jedinečný identifikátor vašeho zařízení (IMSI nebo IMEI).\n\nTo znamená, že byla zaprotokolována vaše poloha, aktivita nebo identita. Jedná se o obvyklý postup, ale pro uživatele, kterým záleží na ochraně soukromí, to může být problém."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Připojení k zašifrované síti <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"Připojení k SIM kartě <xliff:g id="NETWORK_NAME">%1$s</xliff:g> je teď bezpečnější"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Připojení k nezašifrované síti"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Hovory, zprávy a data jsou teď při používání SIM karty <xliff:g id="NETWORK_NAME">%1$s</xliff:g> zranitelnější"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Hovory, zprávy a data jsou teď při používání SIM karty <xliff:g id="NETWORK_NAME">%1$s</xliff:g> zranitelnější.\n\nJakmile bude připojení opět šifrováno, dostanete další oznámení."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Nastavení zabezpečení mobilních sítí"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Další informace"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"Rozumím"</string>
<string name="fcComplete" msgid="1080909484660507044">"Požadavek zadaný pomocí kódu funkce byl úspěšně dokončen."</string>
<string name="fcError" msgid="5325116502080221346">"Problém s připojením nebo neplatný kód funkce."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -2158,6 +2146,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Informační oznámení režimu sledu činností"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Zapnul se spořič baterie"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Je třeba snížit využití baterie za účelem prodloužení její výdrže"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"Spořič baterie je zapnutý"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"Spořič baterie je zapnutý a prodlužuje výdrž baterie"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Spořič baterie"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Spořič baterie je vypnutý"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Telefon je dostatečně nabitý. Funkce už nejsou omezeny."</string>
@@ -2232,10 +2222,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Přepnout na pracovní aplikaci?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Vaše organizace dovoluje volat jen z pracovních aplikací"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Vaše organizace dovoluje odesílat zprávy jen z pracovních aplikací"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Telefonovat můžete pouze z osobní aplikace Telefon. Takto uskutečněné hovory budou přidány do vaší osobní historie volání."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"Zprávy SMS můžete odesílat jen z osobní aplikace Zprávy."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Použít osobní prohlížeč"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Použít pracovní prohlížeč"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Volat"</string>
@@ -2415,8 +2403,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Práce 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Komunální"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Pracovní profil"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Soukromý prostor"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Klon"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Komunální"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Obsah citlivých oznámení je skrytý"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Obsah aplikace je z bezpečnostních důvodů při sdílení obrazovky skryt"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Automaticky připojeno k satelitu"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 9fb4605..9bd374a 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> efter <xliff:g id="TIME_DELAY">{2}</xliff:g> sekunder"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Ikke viderestillet"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Ikke viderestillet"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Mobilnetværkssikkerhed"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Kryptering, notifikationer for ikke-krypterede netværk"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"Enheds-id\'et blev tilgået"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"Kl. <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> registrerede et netværk i nærheden din enheds unikke id (IMSI eller IMEI), da du brugte dit <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>-SIM"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"Kl. <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> registrerede et netværk i nærheden din enheds unikke id (IMSI eller IMEI), da du brugte dit <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>-SIM.\n\nDet vil sige, at din lokation, din aktivitet eller din identitet er blevet logget. Dette er helt normalt, men kan være et problem for folk, der er bekymrede for deres privatliv."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Der er oprettet forbindelse til det krypterede netværk <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>-SIM-forbindelsen er nu mere sikker"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Der er oprettet forbindelse til et ikke-krypteret netværk"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Opkald, beskeder og data er i øjeblikket mere sårbare, når du bruger dit <xliff:g id="NETWORK_NAME">%1$s</xliff:g>-SIM"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Opkald, beskeder og data er i øjeblikket mere sårbare, når du bruger dit <xliff:g id="NETWORK_NAME">%1$s</xliff:g>-SIM.\n\nNår din forbindelse er krypteret igen, får du en ny notifikation."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Indstillinger for mobilnetværkssikkerhed"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Få flere oplysninger"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"OK"</string>
<string name="fcComplete" msgid="1080909484660507044">"Funktionskoden er komplet."</string>
<string name="fcError" msgid="5325116502080221346">"Forbindelsesproblemer eller ugyldig funktionskode."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -371,8 +359,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Tag screenshot"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Kan tage et screenshot af skærmen."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Preview, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"luk"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"deaktivere eller redigere statuslinje"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Tillader, at appen kan deaktivere statusbjælken eller tilføje og fjerne systemikoner."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"vær statusbjælken"</string>
@@ -2157,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Notifikation med oplysninger om rutinetilstand"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Batterisparefunktion er aktiveret"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Reducerer batteriforbruget for at forlænge batteritiden"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"Batterisparefunktion er aktiveret"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"Batterisparefunktion er aktiveret for at forlænge batteritiden"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Batterisparefunktion"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Batterisparefunktion blev slået fra"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Telefonen har tilstrækkeligt batteri. Funktionerne er ikke længere begrænsede."</string>
@@ -2231,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Vil du skifte til en arbejdsapp?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Din organisation tillader kun, at du foretager opkald via arbejdsapps"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Din organisation tillader kun, at du sender beskeder via arbejdsapps"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Du kan kun foretage telefonopkald fra din personlige opkaldsapp. Opkald, der foretages med din personlige opkaldsapp, føjes til din personlige opkaldshistorik."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"Du kan kun sende sms-beskeder fra din personlige beskedapp."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Brug personlig browser"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Brug arbejdsbrowser"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Ring op"</string>
@@ -2414,8 +2401,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Arbejde 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Fælles"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Arbejdsprofil"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Privat område"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Klon"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Fælles"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Følsomt indhold i notifikationen er skjult"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Af sikkerhedsmæssige årsager vises appindhold ikke ved skærmdeling"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Der blev automatisk oprettet forbindelse til satellit"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 7210fa7..24a71b5 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g><xliff:g id="DIALING_NUMBER">{1}</xliff:g> nach <xliff:g id="TIME_DELAY">{2}</xliff:g> Sekunden."</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nicht weitergeleitet"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nicht weitergeleitet"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Sicherheit des Mobilfunknetzes"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Verschlüsselung, Benachrichtigungen für unverschlüsselte Netzwerke"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"Auf Geräte-ID zugegriffen"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"Um <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> hat ein Netzwerk in der Nähe die eindeutige ID (IMSI oder IMEI) deines Geräts aufgezeichnet, während du deine <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>-SIM verwendet hast."</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"Um <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> hat ein Netzwerk in der Nähe die eindeutige ID (IMSI oder IMEI) deines Geräts aufgezeichnet, während du deine <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>-SIM verwendet hast.\n\nDaher wurden dein Standort, deine Aktivitäten oder deine Identität protokolliert. Das ist zwar üblich, kann jedoch ein Problem für Personen sein, denen ihre Privatsphäre wichtig ist."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Mit verschlüsseltem Netzwerk „<xliff:g id="NETWORK_NAME">%1$s</xliff:g>“ verbunden"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"Verbindung der <xliff:g id="NETWORK_NAME">%1$s</xliff:g>-SIM ist jetzt sicherer"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Mit unverschlüsseltem Netzwerk verbunden"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Anrufe, Nachrichten und Daten sind momentan anfälliger für Angriffe, während du deine <xliff:g id="NETWORK_NAME">%1$s</xliff:g>-SIM verwendest"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Anrufe, Nachrichten und Daten sind momentan anfälliger für Angriffe, während du deine <xliff:g id="NETWORK_NAME">%1$s</xliff:g>-SIM verwendest.\n\nWenn deine Verbindung wieder verschlüsselt ist, erhältst du eine weitere Benachrichtigung."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Einstellungen für die Sicherheit des Mobilfunknetzes"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Weitere Informationen"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"Ok"</string>
<string name="fcComplete" msgid="1080909484660507044">"Funktionscode abgeschlossen"</string>
<string name="fcError" msgid="5325116502080221346">"Verbindungsproblem oder ungültiger Funktionscode"</string>
<string name="httpErrorOk" msgid="6206751415788256357">"Ok"</string>
@@ -1154,12 +1142,12 @@
<string name="year" msgid="5182610307741238982">"Jahr"</string>
<string name="years" msgid="5797714729103773425">"Jahre"</string>
<string name="now_string_shortest" msgid="3684914126941650330">"Jetzt"</string>
- <string name="duration_minutes_shortest" msgid="5744379079540806690">"<xliff:g id="COUNT">%d</xliff:g> min"</string>
- <string name="duration_hours_shortest" msgid="1477752094141971675">"<xliff:g id="COUNT">%d</xliff:g> h"</string>
+ <string name="duration_minutes_shortest" msgid="5744379079540806690">"<xliff:g id="COUNT">%d</xliff:g> Min."</string>
+ <string name="duration_hours_shortest" msgid="1477752094141971675">"<xliff:g id="COUNT">%d</xliff:g> Std."</string>
<string name="duration_days_shortest" msgid="4083124701676227233">"<xliff:g id="COUNT">%d</xliff:g> T"</string>
<string name="duration_years_shortest" msgid="483982719231145618">"<xliff:g id="COUNT">%d</xliff:g> J"</string>
- <string name="duration_minutes_shortest_future" msgid="5260857299282734759">"in <xliff:g id="COUNT">%d</xliff:g> min"</string>
- <string name="duration_hours_shortest_future" msgid="2979276794547981674">"in <xliff:g id="COUNT">%d</xliff:g> h"</string>
+ <string name="duration_minutes_shortest_future" msgid="5260857299282734759">"in <xliff:g id="COUNT">%d</xliff:g> Min."</string>
+ <string name="duration_hours_shortest_future" msgid="2979276794547981674">"in <xliff:g id="COUNT">%d</xliff:g> Std."</string>
<string name="duration_days_shortest_future" msgid="3392722163935571543">"in <xliff:g id="COUNT">%d</xliff:g> T"</string>
<string name="duration_years_shortest_future" msgid="5537464088352970388">"in <xliff:g id="COUNT">%d</xliff:g> J"</string>
<string name="duration_minutes_relative" msgid="8620337701051015593">"{count,plural, =1{Vor # Minute}other{Vor # Minuten}}"</string>
@@ -2156,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Infomitteilung zum Ablaufmodus"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Energiesparmodus aktiviert"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Reduzierung der Akkunutzung, um die Akkulaufzeit zu verlängern"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"Energiesparmodus ist aktiviert"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"Der Energiesparmodus ist aktiviert, um die Akkulaufzeit zu verlängern"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Energiesparmodus"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Energiesparmodus deaktiviert"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Das Smartphone ist ausreichend geladen. Es sind keine Funktionen mehr beschränkt."</string>
@@ -2230,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Zu geschäftlicher App wechseln?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Deine Organisation lässt das Telefonieren nur über geschäftliche Apps zu"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Deine Organisation lässt das Senden von Nachrichten nur über geschäftliche Apps zu"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Du kannst nur über deine persönliche Telefon App telefonieren. Über die persönliche Telefon App getätigte Anrufe werden deiner persönlichen Anrufliste hinzugefügt."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"Du kannst nur über deine persönliche Messages App SMS senden."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Privaten Browser verwenden"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Arbeitsbrowser verwenden"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Anrufen"</string>
@@ -2406,15 +2394,18 @@
<string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Tastaturlayout festgelegt auf <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… Zum Ändern tippen."</string>
<string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Physische Tastaturen konfiguriert"</string>
<string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Zum Ansehen der Tastaturen tippen"</string>
- <string name="profile_label_private" msgid="6463418670715290696">"Privat"</string>
+ <string name="profile_label_private" msgid="6463418670715290696">"Vertraulich"</string>
<string name="profile_label_clone" msgid="769106052210954285">"Klon"</string>
<string name="profile_label_work" msgid="3495359133038584618">"Geschäftlich"</string>
<string name="profile_label_work_2" msgid="4691533661598632135">"Geschäftlich 2"</string>
<string name="profile_label_work_3" msgid="4834572253956798917">"Geschäftlich 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Gemeinsam genutzt"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Arbeitsprofil"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Vertrauliches Profil"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Klon"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Gemeinsam genutzt"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Vertrauliche Benachrichtigungsinhalte ausgeblendet"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"App-Inhalte werden aus Sicherheitsgründen bei der Bildschirmfreigabe ausgeblendet"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Automatisch mit Satellit verbunden"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index c585376..32611ef 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> μετά από <xliff:g id="TIME_DELAY">{2}</xliff:g> δευτερόλεπτα"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Δεν προωθήθηκε"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Δεν προωθήθηκε"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Ασφάλεια δικτύου κινητής τηλεφωνίας"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Κρυπτογράφηση, ειδοποιήσεις για μη κρυπτογραφημένα δίκτυα"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"Πρόσβαση στο αναγνωριστικό συσκευής"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"Στις <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, ένα κοντινό δίκτυο κατέγραψε το μοναδικό αναγνωριστικό της συσκευής σας (IMSI ή IMEI) κατά τη χρήση της SIM <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"Στις <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, ένα κοντινό δίκτυο κατέγραψε το μοναδικό αναγνωριστικό της συσκευής σας (IMSI ή IMEI) κατά τη χρήση της SIM <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>.\n\nΑυτό σημαίνει ότι καταγράφηκε η τοποθεσία, η δραστηριότητα ή η ταυτότητά σας. Πρόκειται για συνήθη πρακτική, αλλά μπορεί να αποτελεί πρόβλημα για άτομα που ανησυχούν για το απόρρητό τους."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Έγινε σύνδεση στο κρυπτογραφημένο δίκτυο <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"Η σύνδεση της SIM <xliff:g id="NETWORK_NAME">%1$s</xliff:g> είναι πλέον πιο ασφαλής"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Έγινε σύνδεση σε μη κρυπτογραφημένο δίκτυο"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Αυτή τη στιγμή, οι κλήσεις, τα μηνύματα και τα δεδομένα είναι πιο ευάλωτα κατά τη χρήση της SIM <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Αυτή τη στιγμή, οι κλήσεις, τα μηνύματα και τα δεδομένα είναι πιο ευάλωτα κατά τη χρήση της SIM <xliff:g id="NETWORK_NAME">%1$s</xliff:g>.\n\nΌταν ενεργοποιηθεί ξανά η κρυπτογράφηση της σύνδεσής σας, θα λάβετε μία ακόμη ειδοποίηση."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Ρυθμίσεις ασφάλειας δικτύου κινητής τηλεφωνίας"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Μάθετε περισσότερα"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"Το κατάλαβα"</string>
<string name="fcComplete" msgid="1080909484660507044">"Ο κωδικός λειτουργίας ολοκληρώθηκε."</string>
<string name="fcError" msgid="5325116502080221346">"Πρόβλημα σύνδεσης ή μη έγκυρος κώδικας δυνατότητας."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -2156,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Ειδοποίηση πληροφοριών λειτουργίας Ρουτίνας"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Η Εξοικονόμηση μπαταρίας ενεργοποιήθηκε"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Μείωση της χρήσης της μπαταρίας για παράταση της διάρκειας ζωής της μπαταρίας"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"Η Εξοικονόμηση μπαταρίας είναι ενεργή"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"Η Εξοικονόμηση μπαταρίας ενεργοποιήθηκε για την παράταση της διάρκειας ζωής της μπαταρίας"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Εξοικονόμηση μπαταρίας"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Η Εξοικονόμηση μπαταρίας απενεργοποιήθηκε"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Το τηλέφωνο είναι αρκετά φορτισμένο. Οι λειτουργίες δεν περιορίζονται πλέον."</string>
@@ -2230,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Εναλλαγή σε εφαρμογή εργασιών;"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Ο οργανισμός σας επιτρέπει την πραγματοποίηση κλήσεων μόνο από εφαρμογές εργασιών"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Ο οργανισμός σας επιτρέπει την αποστολή μηνυμάτων μόνο από εφαρμογές εργασιών"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Μπορείτε να κάνετε τηλεφωνικές κλήσεις μόνο από την προσωπική εφαρμογή Τηλέφωνο. Οι κλήσεις που γίνονται με την προσωπική εφαρμογή Τηλέφωνο θα προστίθενται στο προσωπικό ιστορικό κλήσεων."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"Μπορείτε να στέλνετε μηνύματα SMS μόνο από την προσωπική εφαρμογή Messages."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Χρήση προσωπικού προγράμματος περιήγησης"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Χρήση προγράμματος περιήγησης εργασίας"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Κλήση"</string>
@@ -2413,8 +2401,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Εργασία 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Δοκιμή"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Κοινόχρηστο"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Προφίλ εργασίας"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Απόρρητος χώρος"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Κλώνος"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Κοινόχρηστο"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Έγινε απόκρυψη της ειδοποίησης ευαίσθητου περιεχομένου"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Για λόγους ασφάλειας, έγινε απόκρυψη του περιεχομένου της εφαρμογής από την κοινή χρήση οθόνης"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Συνδέθηκε αυτόματα με δορυφόρο"</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index aa22491..1e1a687 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> after <xliff:g id="TIME_DELAY">{2}</xliff:g> seconds"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Not forwarded"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Not forwarded"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Mobile network security"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Encryption, notifications for unencrypted networks"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"Device ID accessed"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"At <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, a nearby network recorded your device\'s unique ID (IMSI or IMEI) while using your <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> SIM"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"At <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, a nearby network recorded your device\'s unique ID (IMSI or IMEI) while using your <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> SIM.\n\nThis means that your location, activity or identity have been logged. This is common practice but may be an issue for people concerned about privacy."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Connected to encrypted network <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM connection is more secure now"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Connected to unencrypted network"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Calls, messages and data are currently more vulnerable while using your <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Calls, messages and data are currently more vulnerable while using your <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM.\n\nWhen your connection is encrypted again, you\'ll get another notification."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Mobile network security settings"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Learn more"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"Got it"</string>
<string name="fcComplete" msgid="1080909484660507044">"Feature code complete."</string>
<string name="fcError" msgid="5325116502080221346">"Connection problem or invalid feature code."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -371,8 +359,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Take screenshot"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Can take a screenshot of the display."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Preview, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"dismiss"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"disable or modify status bar"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Allows the app to disable the status bar or add and remove system icons."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"be the status bar"</string>
@@ -2157,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Routine Mode info notification"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Battery Saver turned on"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Reducing battery usage to extend battery life"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"Battery Saver is on"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"Battery Saver is turned on to extend battery life"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Battery Saver"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Battery Saver turned off"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Phone has enough charge. Features no longer restricted."</string>
@@ -2231,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Switch to work app?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Your organisation only allows you to make calls from work apps"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Your organisation only allows you to send messages from work apps"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"You can only make phone calls from your personal Phone app. Calls made with your personal Phone app will be added to your personal call history."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"You can only send SMS messages from your personal Messages app."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Use personal browser"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Use work browser"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Call"</string>
@@ -2414,6 +2401,10 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Work 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Communal"</string>
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Work profile"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Private space"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Clone"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Communal"</string>
<string name="redacted_notification_message" msgid="1520587845842228816">"Sensitive notification content hidden"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"App content hidden from screen share for security"</string>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index ad376b8..9951afd 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -2144,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Routine Mode info notification"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Battery Saver turned on"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Reducing battery usage to extend battery life"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"Battery Saver is on"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"Battery Saver is turned on to extend battery life"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Battery Saver"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Battery Saver turned off"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Phone has enough charge. Features no longer restricted."</string>
@@ -2399,6 +2401,10 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Work 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Communal"</string>
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Work profile"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Private space"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Clone"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Communal"</string>
<string name="redacted_notification_message" msgid="1520587845842228816">"Sensitive notification content hidden"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"App content hidden from screen share for security"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index e9bd5b3..8d55681 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> after <xliff:g id="TIME_DELAY">{2}</xliff:g> seconds"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Not forwarded"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Not forwarded"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Mobile network security"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Encryption, notifications for unencrypted networks"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"Device ID accessed"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"At <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, a nearby network recorded your device\'s unique ID (IMSI or IMEI) while using your <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> SIM"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"At <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, a nearby network recorded your device\'s unique ID (IMSI or IMEI) while using your <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> SIM.\n\nThis means that your location, activity or identity have been logged. This is common practice but may be an issue for people concerned about privacy."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Connected to encrypted network <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM connection is more secure now"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Connected to unencrypted network"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Calls, messages and data are currently more vulnerable while using your <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Calls, messages and data are currently more vulnerable while using your <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM.\n\nWhen your connection is encrypted again, you\'ll get another notification."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Mobile network security settings"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Learn more"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"Got it"</string>
<string name="fcComplete" msgid="1080909484660507044">"Feature code complete."</string>
<string name="fcError" msgid="5325116502080221346">"Connection problem or invalid feature code."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -371,8 +359,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Take screenshot"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Can take a screenshot of the display."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Preview, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"dismiss"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"disable or modify status bar"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Allows the app to disable the status bar or add and remove system icons."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"be the status bar"</string>
@@ -2157,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Routine Mode info notification"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Battery Saver turned on"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Reducing battery usage to extend battery life"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"Battery Saver is on"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"Battery Saver is turned on to extend battery life"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Battery Saver"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Battery Saver turned off"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Phone has enough charge. Features no longer restricted."</string>
@@ -2231,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Switch to work app?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Your organisation only allows you to make calls from work apps"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Your organisation only allows you to send messages from work apps"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"You can only make phone calls from your personal Phone app. Calls made with your personal Phone app will be added to your personal call history."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"You can only send SMS messages from your personal Messages app."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Use personal browser"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Use work browser"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Call"</string>
@@ -2414,6 +2401,10 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Work 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Communal"</string>
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Work profile"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Private space"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Clone"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Communal"</string>
<string name="redacted_notification_message" msgid="1520587845842228816">"Sensitive notification content hidden"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"App content hidden from screen share for security"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index ec45a4c..a8e397d 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> after <xliff:g id="TIME_DELAY">{2}</xliff:g> seconds"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Not forwarded"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Not forwarded"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Mobile network security"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Encryption, notifications for unencrypted networks"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"Device ID accessed"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"At <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, a nearby network recorded your device\'s unique ID (IMSI or IMEI) while using your <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> SIM"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"At <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, a nearby network recorded your device\'s unique ID (IMSI or IMEI) while using your <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> SIM.\n\nThis means that your location, activity or identity have been logged. This is common practice but may be an issue for people concerned about privacy."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Connected to encrypted network <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM connection is more secure now"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Connected to unencrypted network"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Calls, messages and data are currently more vulnerable while using your <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Calls, messages and data are currently more vulnerable while using your <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM.\n\nWhen your connection is encrypted again, you\'ll get another notification."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Mobile network security settings"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Learn more"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"Got it"</string>
<string name="fcComplete" msgid="1080909484660507044">"Feature code complete."</string>
<string name="fcError" msgid="5325116502080221346">"Connection problem or invalid feature code."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -371,8 +359,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Take screenshot"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Can take a screenshot of the display."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Preview, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"dismiss"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"disable or modify status bar"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Allows the app to disable the status bar or add and remove system icons."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"be the status bar"</string>
@@ -2157,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Routine Mode info notification"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Battery Saver turned on"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Reducing battery usage to extend battery life"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"Battery Saver is on"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"Battery Saver is turned on to extend battery life"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Battery Saver"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Battery Saver turned off"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Phone has enough charge. Features no longer restricted."</string>
@@ -2231,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Switch to work app?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Your organisation only allows you to make calls from work apps"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Your organisation only allows you to send messages from work apps"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"You can only make phone calls from your personal Phone app. Calls made with your personal Phone app will be added to your personal call history."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"You can only send SMS messages from your personal Messages app."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Use personal browser"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Use work browser"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Call"</string>
@@ -2414,6 +2401,10 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Work 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Communal"</string>
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Work profile"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Private space"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Clone"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Communal"</string>
<string name="redacted_notification_message" msgid="1520587845842228816">"Sensitive notification content hidden"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"App content hidden from screen share for security"</string>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index 4c72d6a..e7f713b 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -2144,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Routine Mode info notification"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Battery Saver turned on"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Reducing battery usage to extend battery life"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"Battery Saver is on"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"Battery Saver is turned on to extend battery life"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Battery Saver"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Battery Saver turned off"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Phone has enough charge. Features no longer restricted."</string>
@@ -2399,6 +2401,10 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Work 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Communal"</string>
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Work profile"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Private space"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Clone"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Communal"</string>
<string name="redacted_notification_message" msgid="1520587845842228816">"Sensitive notification content hidden"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"App content hidden from screen share for security"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 387381f..5d4e951 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -154,31 +154,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> después de <xliff:g id="TIME_DELAY">{2}</xliff:g> segundos"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: no se ha remitido"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: no se ha remitido"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Seguridad de redes móviles"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Encriptación, notificaciones para redes no encriptadas"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"Se accedió al ID de dispositivo"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"A la(s) <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, una red cercana registró el ID único de tu dispositivo (IMSI o IMEI) mientras se usaba tu SIM de <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"A la(s) <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, una red cercana registró el ID único de tu dispositivo (IMSI o IMEI) mientras se usaba tu SIM de <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>.\n\nEsto significa que se registró tu ubicación, actividad o identidad. Esta es una práctica común, pero podría significar un problema para personas preocupadas por su privacidad."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Se conectó a la red encriptada de <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"La conexión de la SIM de <xliff:g id="NETWORK_NAME">%1$s</xliff:g> ahora es más segura"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Conexión con una red no encriptada"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Cuando usas la SIM de <xliff:g id="NETWORK_NAME">%1$s</xliff:g>, las llamadas, los mensajes y los datos son más vulnerables"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Cuando usas la SIM de <xliff:g id="NETWORK_NAME">%1$s</xliff:g>, las llamadas, los mensajes y los datos son más vulnerables.\n\nRecibirás otra notificación cuando se vuelva a encriptar tu conexión."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Configuración de la seguridad de redes móviles"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Más información"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"Entendido"</string>
<string name="fcComplete" msgid="1080909484660507044">"Código de función completo."</string>
<string name="fcError" msgid="5325116502080221346">"Problema de conexión o código de función no válido."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"Aceptar"</string>
@@ -372,8 +360,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Tomar captura de pantalla"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Puede tomar capturas de pantalla."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Vista previa, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"descartar"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"desactivar o modificar la barra de estado"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Permite que la aplicación inhabilite la barra de estado o que agregue y elimine íconos del sistema."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"aparecer en la barra de estado"</string>
@@ -2158,6 +2145,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Notificación de información del modo de Rutinas"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Ahorro de batería activado"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Reduciendo el uso de la batería para extender su duración"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"El Ahorro de batería está activado"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"Se activó el Ahorro de batería para extender la duración de batería"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Ahorro de batería"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Se desactivó el Ahorro de batería"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"El teléfono tiene suficiente carga. Ya no se restringen las funciones."</string>
@@ -2232,10 +2221,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"¿Quieres cambiar a una app de trabajo?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Tu organización solo te permite realizar llamadas desde apps de trabajo"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Tu organización solo te permite enviar mensajes desde apps de trabajo"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Solo puedes realizar llamadas desde tu app de Teléfono personal. Las llamadas que hagas con el Teléfono personal se agregarán a tu historial de llamadas personal."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"Solo puedes enviar mensajes SMS desde tu app de Mensajes personal."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Usar un navegador personal"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Usar un navegador de trabajo"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Llamar"</string>
@@ -2415,8 +2402,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Trabajo 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Probar"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Compartido"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Perfil de trabajo"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Espacio privado"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Clon"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Compartido"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Se ocultó contenido sensible de la notificación"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Se ocultó el contenido de la app durante el uso compartido de la pantalla por motivos de seguridad"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Conexión automática a satélite"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index bad3cdd..19be81f 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -154,31 +154,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> transcurridos <xliff:g id="TIME_DELAY">{2}</xliff:g> segundos"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: No desviada"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: No desviada"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Seguridad de redes móviles"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Cifrado, notificaciones sobre redes no cifradas"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"Se ha accedido al ID del dispositivo"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"A las <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, una red cercana registró el ID único de tu dispositivo (IMSI o IMEI) mientras usabas la SIM de <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"A las <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, una red cercana registró el ID único de tu dispositivo (IMSI o IMEI) mientras usabas la SIM de <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>.\n\nEsto significa que se ha registrado tu ubicación, actividad o identidad. Se trata de una práctica habitual, pero puede ser un problema para aquellos a quienes les preocupa su privacidad."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Conectado a la red cifrada <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"Ahora, la conexión con la SIM de <xliff:g id="NETWORK_NAME">%1$s</xliff:g> es más segura"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Conectado a una red no cifrada"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Tus llamadas, mensajes y datos son más vulnerables mientras uses la SIM de <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Tus llamadas, mensajes y datos son más vulnerables mientras uses la SIM de <xliff:g id="NETWORK_NAME">%1$s</xliff:g>.\n\nCuando tu conexión vuelva a cifrarse, recibirás una notificación."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Ajustes de seguridad de redes móviles"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Más información"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"Entendido"</string>
<string name="fcComplete" msgid="1080909484660507044">"Código de función completo"</string>
<string name="fcError" msgid="5325116502080221346">"Se ha producido un problema de conexión o el código de la función no es válido."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"Aceptar"</string>
@@ -372,8 +360,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Hacer captura"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Puede hacer capturas de la pantalla."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Vista previa, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"cerrar"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"inhabilitar o modificar la barra de estado"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Permite que la aplicación inhabilite la barra de estado o añada y elimine iconos del sistema."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"aparecer en la barra de estado"</string>
@@ -2158,6 +2145,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Notificación sobre el modo rutina"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Ahorro de batería activado"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Reduciendo el uso de batería para prolongar su duración"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"Ahorro de batería activado"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"Se ha activado Ahorro de batería para prolongar la duración de la batería"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Ahorro de batería"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Ahorro de batería desactivado"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"El teléfono tiene suficiente batería. Las funciones ya no están restringidas."</string>
@@ -2232,10 +2221,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"¿Cambiar a la aplicación de trabajo?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Tu organización solo te permite hacer llamadas desde aplicaciones de trabajo"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Tu organización solo te permite enviar mensajes desde aplicaciones de trabajo"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Solo puedes hacer llamadas desde tu aplicación personal Teléfono. Las llamadas que hagas desde Teléfono se añadirán a tu historial de llamadas."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"Solo puedes enviar mensajes SMS desde tu aplicación personal Mensajes."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Usar navegador personal"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Usar navegador de trabajo"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Llamar"</string>
@@ -2415,8 +2402,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Trabajo 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Prueba"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Común"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Perfil de trabajo"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Espacio privado"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Clon"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Común"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Contenido sensible de la notificación oculto"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Contenido de la aplicación oculto en pantalla compartida por motivos de seguridad"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Conectado automáticamente al satélite"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 7364183..4a17e0d 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> sekundi pärast"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: pole suunatud"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: pole edastatud"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Mobiilsidevõrgu turve"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Krüpteerimine, märguanded krüpteerimata võrkude jaoks"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"Seadme ID-le on juurde pääsetud"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"Kell <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> salvestas lähedal olev võrk võrgu <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> SIM-i kasutamise ajal teie seadme kordumatu ID (IMSI või IMEI)"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"Kell <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> salvestas lähedal olev võrk võrgu <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> SIM-i kasutamise ajal teie seadme kordumatu ID (IMSI või IMEI).\n\nSee tähendab, et teie asukoht, tegevus või isik salvestati. See on levinud tava, kuid võib osutada probleemiks inimeste jaoks, kellele on privaatsus eriti oluline."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Ühendatud krüpteeritud võrguga <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"Võrgu <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM-i ühendus on nüüd turvalisem"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Ühendatud krüpteerimata võrguga"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Võrgu <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM-i kasutamisel on teie kõned, sõnumid ja andmed praegu haavatavamad"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Võrgu <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM-i kasutamisel on teie kõned, sõnumid ja andmed praegu haavatavamad.\n\nKui teie ühendus on taas krüpteeritud, saate veel ühe märguande."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Mobiilsidevõrgu turvaseaded"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Lisateave"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"Selge"</string>
<string name="fcComplete" msgid="1080909484660507044">"Funktsioonikood valmis."</string>
<string name="fcError" msgid="5325116502080221346">"Ühendusprobleem või kehtetu funktsioonikood."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -371,8 +359,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Jäädvusta ekraanipilt"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Saab jäädvustada ekraanipildi."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Eelvaade, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"loobu"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"keela või muuda olekuriba"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Võimaldab rakendusel keelata olekuriba või lisada ja eemaldada süsteemiikoone."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"olekuribana kuvamine"</string>
@@ -2157,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Rutiinirežiimi teabe märguanne"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Akusäästja lülitati sisse"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Aku tööea pikendamiseks vähendatakse akukasutust"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"Akusäästja on sisse lülitatud"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"Akusäästja on sisse lülitatud, et pikendada aku tööiga"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Akusäästja"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Akusäästja on välja lülitatud"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Telefon on piisavalt laetud. Funktsioonid ei ole enam piiratud."</string>
@@ -2231,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Kas lülituda töörakendusele?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Teie organisatsioon lubab helistada ainult töörakendustest."</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Teie organisatsioon lubab sõnumeid saata ainult töörakendustest."</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Saate helistada ainult oma isiklikust rakendusest Telefon. Isikliku rakendusesega Telefon tehtud kõned lisatakse teie isiklikku kõneajalukku."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"Saate saata SMS-sõnumeid ainult oma isiklikust rakendusest Messages."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Kasuta isiklikku brauserit"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Kasuta tööbrauserit"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Helista"</string>
@@ -2414,6 +2401,10 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Töö 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Jagatud"</string>
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Tööprofiil"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Privaatne ruum"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Kloon"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Ühine"</string>
<string name="redacted_notification_message" msgid="1520587845842228816">"Märguande delikaatne sisu peideti"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Rakenduse sisu on ekraani jagamises turvalisuse huvides peidetud"</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index b4c054b..3f3404c 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> zenbakira <xliff:g id="TIME_DELAY">{2}</xliff:g> segundotan"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ez da desbideratu"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ez da desbideratu"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Sare mugikorraren segurtasuna"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Enkriptatzea, enkriptatu gabeko sareen jakinarazpenak"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"Gailu-identifikatzailea atzitu da"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"<xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> aldera, inguruko sare batek zure gailuaren identifikatzaile esklusiboa (IMSI edo IMEI) erregistratu du, <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> operadorearen SIMa erabiltzen ari zinenean"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"<xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> aldera, inguruko sare batek zure gailuaren identifikatzaile esklusiboa (IMSI edo IMEI) erregistratu du, <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> operadorearen SIMa erabiltzen ari zinenean.\n\nHorrek esan nahi du zure kokapena, jarduerak edo identitatea erregistratuta geratu direla. Ohikoa da hori, baina baliteke arazo bat izatea pribatutasunari garrantzia ematen dioten pertsonentzat."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> sare enkriptatura konektatuta"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> operadorearen SIMaren konexioa seguruagoa da orain"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Enkriptatu gabeko sare batera konektatuta"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Deiek, mezuek eta datuek arrisku handiagoa dute orain, <xliff:g id="NETWORK_NAME">%1$s</xliff:g> operadorearen SIMa erabiltzen ari zarelako"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Deiek, mezuek eta datuek arrisku handiagoa dute orain, <xliff:g id="NETWORK_NAME">%1$s</xliff:g> operadorearen SIMa erabiltzen ari zarelako.\n\nBeste jakinarazpen bat jasoko duzu konexioa berriro ere enkriptatuta dagoenean."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Sare mugikorraren segurtasun-ezarpenak"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Lortu informazio gehiago"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"Ados"</string>
<string name="fcComplete" msgid="1080909484660507044">"Eginbide-kodea osatu da."</string>
<string name="fcError" msgid="5325116502080221346">"Konexio-arazo bat gertatu da edo eginbide-kodea baliogabea da."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"Ados"</string>
@@ -371,8 +359,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Pantaila-argazkiak atera."</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Pantaila-argazkiak atera ditzake."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Aurrebista, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"baztertu"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"desgaitu edo aldatu egoera-barra"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Egoera-barra desgaitzeko edo sistema-ikonoak gehitzeko edo kentzeko baimena ematen dio aplikazioari."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"bihurtu egoera-barra"</string>
@@ -480,9 +467,9 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Igorpen iraunkorrak egiteko baimena ematen dio aplikazioari. Igorpena amaitu ondoren ere igortzen jarraitzen dute igorpen iraunkorrek. Gehiegi erabiliz gero, Android TV gailua motel edo ezegonkor ibiliko da, memoria gehiago erabiliko delako."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Igorpen iraunkorrak emateko baimena ematen dio aplikazioari; horiek igorpena amaitu ondoren mantentzen dira. Gehiegi erabiliz gero, telefonoa motel edo ezegonkor ibiliko da, memoria gehiago erabiliko delako."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"irakurri kontaktuak"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Tabletan gordetako kontaktuei buruzko datuak irakurtzeko baimena ematen dio aplikazioari. Kontaktuak sortu dituzten tabletako kontuak ere atzitu ahalko ditu aplikazioak. Horrek barnean hartuko ditu instalatutako aplikazioak sortutako kontuak, agian. Baimen horrekin, kontaktuen datuak gorde ditzake aplikazioak, eta baliteke asmo txarreko aplikazioek zuk jakin gabe partekatzea datu horiek."</string>
- <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Android TV gailuan gordetako kontaktuei buruzko datuak irakurtzeko baimena ematen dio aplikazioari. Kontaktuak sortu dituzten Android TV gailuko kontuak ere atzitu ahalko ditu aplikazioak. Horrek barnean hartuko ditu instalatutako aplikazioak sortutako kontuak, agian. Baimen horrekin, kontaktuen datuak gorde ditzake aplikazioak, eta baliteke asmo txarreko aplikazioek zuk jakin gabe partekatzea datu horiek."</string>
- <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Telefonoan gordetako kontaktuei buruzko datuak irakurtzeko baimena ematen dio aplikazioari. Kontaktuak sortu dituzten telefonoko kontuak ere atzitu ahalko ditu aplikazioak. Horrek barnean hartuko ditu instalatutako aplikazioak sortutako kontuak, agian. Baimen horrekin, kontaktuen datuak gorde ditzake aplikazioak, eta baliteke asmo txarreko aplikazioek zuk jakin gabe partekatzea datu horiek."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Tabletan biltegiratutako kontaktuei buruzko datuak irakurtzeko baimena ematen dio aplikazioari. Kontaktuak sortu dituzten tabletako kontuak ere atzitu ahalko ditu aplikazioak. Horrek barnean hartuko ditu instalatutako aplikazioak sortutako kontuak, agian. Baimen horrekin, kontaktuen datuak gorde ditzake aplikazioak, eta baliteke asmo txarreko aplikazioek zuk jakin gabe partekatzea datu horiek."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Android TV gailuan biltegiratutako kontaktuei buruzko datuak irakurtzeko baimena ematen dio aplikazioari. Kontaktuak sortu dituzten Android TV gailuko kontuak ere atzitu ahalko ditu aplikazioak. Horrek barnean hartuko ditu instalatutako aplikazioak sortutako kontuak, agian. Baimen horrekin, kontaktuen datuak gorde ditzake aplikazioak, eta baliteke asmo txarreko aplikazioek zuk jakin gabe partekatzea datu horiek."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Telefonoan biltegiratutako kontaktuei buruzko datuak irakurtzeko baimena ematen dio aplikazioari. Kontaktuak sortu dituzten telefonoko kontuak ere atzitu ahalko ditu aplikazioak. Horrek barnean hartuko ditu instalatutako aplikazioak sortutako kontuak, agian. Baimen horrekin, kontaktuen datuak gorde ditzake aplikazioak, eta baliteke asmo txarreko aplikazioek zuk jakin gabe partekatzea datu horiek."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"aldatu kontaktuak"</string>
<string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Tabletan gordetako kontaktuei buruzko datuak aldatzeko baimena ematen dio aplikazioari. Baimen horrekin, aplikazioak kontaktuen datuak ezaba ditzake."</string>
<string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Android TV gailuan gordetako kontaktuei buruzko datuak aldatzeko baimena ematen dio aplikazioari. Baimen horrekin, aplikazioak kontaktuen datuak ezaba ditzake."</string>
@@ -498,9 +485,9 @@
<string name="permlab_bodySensors_background" msgid="4912560779957760446">"Atzitu gorputz-sentsoreen datuak (adib., bihotz-maiztasunarenak) atzeko planoan"</string>
<string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Aplikazioa atzeko planoan egon bitartean, gorputz-sentsoreen datuak (besteak beste, bihotz-maiztasuna, tenperatura eta odolean dagoen oxigenoaren ehunekoa) erabiltzeko baimena ematen dio aplikazioari."</string>
<string name="permlab_readCalendar" msgid="6408654259475396200">"irakurri egutegiko gertaerak eta xehetasunak"</string>
- <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Aplikazioak tabletan gordetako egutegiko gertaerak irakur ditzake eta egutegiko datuak parteka eta gorde ditzake."</string>
- <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Aplikazioak Android TV gailuan gordeta dituzun egutegiko gertaerak irakur ditzake, baita egutegiko datuak partekatu eta gorde ere."</string>
- <string name="permdesc_readCalendar" product="default" msgid="9118823807655829957">"Aplikazioak telefonoan gordetako egutegiko gertaerak irakur ditzake eta egutegiko datuak parteka eta gorde ditzake."</string>
+ <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Aplikazioak tabletan biltegiratutako egutegiko gertaerak irakur ditzake eta egutegiko datuak parteka eta gorde ditzake."</string>
+ <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Aplikazioak Android TV gailuan biltegiratuta dituzun egutegiko gertaerak irakur ditzake, baita egutegiko datuak partekatu eta gorde ere."</string>
+ <string name="permdesc_readCalendar" product="default" msgid="9118823807655829957">"Aplikazioak telefonoan biltegiratutako egutegiko gertaerak irakur ditzake eta egutegiko datuak parteka eta gorde ditzake."</string>
<string name="permlab_writeCalendar" msgid="6422137308329578076">"gehitu edo aldatu egutegiko gertaerak eta bidali mezu elektronikoak gonbidatuei jabeek jakin gabe"</string>
<string name="permdesc_writeCalendar" product="tablet" msgid="8722230940717092850">"Tabletako gertaerak gehitzeko, kentzeko edo aldatzeko aukera du aplikazioak. Gainera, egutegien jabeenak diruditen mezuak bidal ditzake, eta gertaerak alda ditzake jabeei beraiei jakinarazi gabe."</string>
<string name="permdesc_writeCalendar" product="tv" msgid="951246749004952706">"Android TV gailuan egutegiko gertaerak gehitzeko eta gehitutakoak kentzeko edo aldatzeko aukera dute aplikazioek. Gainera, egutegien jabeenak diruditen mezuak bidal ditzakete, edo gertaerak aldatu jabeei ezer esan gabe."</string>
@@ -2157,6 +2144,10 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Ohitura moduaren informazio-jakinarazpena"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Bateria-aurreztailea aktibatu da"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Bateria-erabilera murrizten hasi da haren iraupena luzatzeko"</string>
+ <!-- no translation found for dynamic_mode_notification_title_v2 (5072385242078021152) -->
+ <skip />
+ <!-- no translation found for dynamic_mode_notification_summary_v2 (2142444344663147938) -->
+ <skip />
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Bateria-aurreztailea"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Desaktibatu egin da bateria-aurreztailea"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Behar adina bateria dauka telefonoak. Jada ez dago eginbiderik murriztuta."</string>
@@ -2231,10 +2222,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Laneko aplikaziora aldatu nahi duzu?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Laneko aplikazioetatik soilik deitzeko baimena ematen du zure erakundeak"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Mezuak laneko aplikazioetatik soilik bidaltzeko baimena ematen du zure erakundeak"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Telefono-deiak egiteko, Telefonoa aplikazio pertsonala soilik erabil dezakezu. Deien historia pertsonalean gehituko dira Telefonoa aplikazio pertsonalarekin egindako deiak."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"SMS mezuak bidaltzeko, Mezuak aplikazio pertsonala soilik erabil dezakezu."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Erabili arakatzaile pertsonala"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Erabili laneko arakatzailea"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Deitu"</string>
@@ -2414,8 +2403,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Lanekoa 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Probakoa"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Partekatua"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Laneko profila"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Eremu pribatua"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Klona"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Partekatua"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Jakinarazpenaren kontuzko edukia ezkutatu da"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Aplikazioko edukia ezkutatu egin da pantaila partekatzeko eginbidetik, segurtasuna bermatzeko"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Automatikoki konektatu da satelitera"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index db06309..3f850c1 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> پس از <xliff:g id="TIME_DELAY">{2}</xliff:g> ثانیه"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: هدایت نشده"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: هدایت نشده"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"امنیت شبکه تلفن همراه"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"رمزگذاری، اعلانهای شبکههای رمزگذارینشده"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"شناسه دستگاه دردسترس قرار گرفته است"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"ساعت <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>، یکی از شبکههای اطراف شناسه یکتای دستگاهتان (IMSI یا IMEI) را هنگام استفاده از سیمکارت <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> ضبط کرده است"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"ساعت <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>، یکی از شبکههای اطراف شناسه یکتای دستگاهتان (IMSI یا IMEI) را هنگام استفاده از سیمکارت <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> ضبط کرده است.\n\nاین یعنی مکان، فعالیت، یا هویت شما ثبت شده است. این رویکرد عادی است اما ممکن است برای افرادی که نگران حریم خصوصیشان هستند مشکلساز باشد."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"به شبکه رمزگذاریشده <xliff:g id="NETWORK_NAME">%1$s</xliff:g> متصل شدید"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"اتصال سیمکارت <xliff:g id="NETWORK_NAME">%1$s</xliff:g> اکنون ایمنتر است"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"به شبکه رمزگذارینشده متصل شدید"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"درحالحاضر تماسها، پیامها، و دادهها هنگام استفاده از سیمکارت <xliff:g id="NETWORK_NAME">%1$s</xliff:g> آسیبپذیرتر هستند"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"درحالحاضر تماسها، پیامها، و دادهها هنگام استفاده از سیمکارت <xliff:g id="NETWORK_NAME">%1$s</xliff:g> آسیبپذیرتر هستند.\n\nوقتی اتصال شما دوباره رمزگذاری شود، اعلان دیگری دریافت خواهید کرد."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"تنظیمات امنیت شبکه تلفن همراه"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"بیشتر بدانید"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"متوجهام"</string>
<string name="fcComplete" msgid="1080909484660507044">"کد ویژگی کامل شد."</string>
<string name="fcError" msgid="5325116502080221346">"مشکل در اتصال یا کد ویژگی نامعتبر."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"تأیید"</string>
@@ -1916,8 +1904,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"توسط سرپرست سیستم بهروزرسانی شد"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"توسط سرپرست سیستم حذف شد"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"تأیید"</string>
- <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"«بهینهسازی باتری» «زمینه تیره» را روشن میکند و فعالیت پسزمینه، برخی از جلوههای بصری، ویژگیهایی خاص، و برخی از اتصالهای شبکه را محدود یا خاموش میکند."</string>
- <string name="battery_saver_description" msgid="8518809702138617167">"«بهینهسازی باتری» «زمینه تیره» را روشن میکند و فعالیت پسزمینه، برخی از جلوههای بصری، ویژگیهایی خاص، و برخی از اتصالهای شبکه را محدود یا خاموش میکند."</string>
+ <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"«بهینهسازی باتری» «زمینه تاریک» را روشن میکند و فعالیت پسزمینه، برخی از جلوههای بصری، ویژگیهایی خاص، و برخی از اتصالهای شبکه را محدود یا خاموش میکند."</string>
+ <string name="battery_saver_description" msgid="8518809702138617167">"«بهینهسازی باتری» «زمینه تاریک» را روشن میکند و فعالیت پسزمینه، برخی از جلوههای بصری، ویژگیهایی خاص، و برخی از اتصالهای شبکه را محدود یا خاموش میکند."</string>
<string name="data_saver_description" msgid="4995164271550590517">"برای کمک به کاهش مصرف داده، «صرفهجویی داده» از ارسال و دریافت داده در پسزمینه در بعضی برنامهها جلوگیری میکند. برنامهای که درحالحاضر استفاده میکنید میتواند به دادهها دسترسی داشته باشد اما دفعات دسترسی آن محدود است. این میتواند به این معنی باشد که، برای مثال، تصاویر تازمانیکه روی آنها ضربه نزنید نشان داده نمیشوند."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"«صرفهجویی داده» روشن شود؟"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"روشن کردن"</string>
@@ -2156,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"اعلان اطلاعات حالت روال معمول"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"«بهینهسازی باتری» روشن شد"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"برای افزایش عمر باتری، مصرف باتری کاهش مییابد"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"«بهینهسازی باتری» روشن است"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"«بهینهسازی باتری» برای افزایش عمر باتری روشن شد"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"بهینهسازی باتری"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"«بهینهسازی باتری» خاموش شد"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"تلفن بهاندازه کافی شارژ دارد. ویژگیها دیگر محدود نمیشوند."</string>
@@ -2230,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"به برنامه کاری جابهجا شوید؟"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"سازمانتان به شما اجازه میدهد فقط ازطریق برنامههای کاری تماس بگیرید"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"سازمانتان به شما اجازه میدهد فقط ازطریق برنامههای کاری پیام ارسال کنید"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"فقط از برنامه «تلفن» شخصیتان میتوانید تماس تلفنی برقرار کنید. تماسهای برقرارشده با برنامه «تلفن» شخصی به سابقه تماس شخصیتان اضافه خواهد شد."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"فقط از برنامه «پیامنگار» شخصیتان میتوانید پیامک ارسال کنید."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"استفاده از مرورگر شخصی"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"استفاده از مرورگر کاری"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"تماس گرفتن"</string>
@@ -2407,14 +2395,17 @@
<string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"صفحهکلیدهای فیزیکی پیکربندی شدند"</string>
<string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"برای مشاهده صفحهکلیدها ضربه بزنید"</string>
<string name="profile_label_private" msgid="6463418670715290696">"خصوصی"</string>
- <string name="profile_label_clone" msgid="769106052210954285">"مشابهسازی"</string>
+ <string name="profile_label_clone" msgid="769106052210954285">"همسانهسازی"</string>
<string name="profile_label_work" msgid="3495359133038584618">"کار"</string>
<string name="profile_label_work_2" msgid="4691533661598632135">"کار ۲"</string>
<string name="profile_label_work_3" msgid="4834572253956798917">"کار ۳"</string>
<string name="profile_label_test" msgid="9168641926186071947">"آزمایش"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"عمومی"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"نمایه کاری"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"فضای خصوصی"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"همسانهسازی"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"همگانی"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"محتوای اعلان حساس پنهان شده است"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"بهدلایل امنیتی، محتوای برنامه از دید همرسانی صفحهنمایش پنهان شد"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"بهطور خودکار به ماهواره متصل شد"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 1a6e7c4..3e1adc4 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> sekunnin päästä"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ei siirretty"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ei siirretty"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Mobiiliverkkoa koskeva turvallisuus"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Salaus, ilmoitukset salaamattomista verkoista"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"Laitteen tunnus jaettu"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"Klo <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> lähellä oleva verkko tallensi laitteesi yksilöllisen tunnuksen (IMSI tai IMEI), kun käytössä oli SIM-kortti, jonka <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> tarjoaa"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"Klo <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> lähellä oleva verkko tallensi laitteesi yksilöllisen tunnuksen (IMSI tai IMEI), kun käytössä oli SIM-kortti, jonka <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> tarjoaa.\n\nTämä tarkoittaa, että sijaintisi, toimintasi tai henkilöllisyytesi on tallennettu. Tämä on tavallista mutta voi huolestuttaa ihmisiä, jotka ovat tarkkoja yksityisyydestään."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Yhdistetty salattuun verkkoon <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"SIM-yhteys, jonka <xliff:g id="NETWORK_NAME">%1$s</xliff:g> tarjoaa, on nyt turvallisempi"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Yhdistetty salattuun verkkoon"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Puhelut, viestit ja data ovat haavoittuvaisempia, kun käytössä on SIM-kortti, jonka <xliff:g id="NETWORK_NAME">%1$s</xliff:g> tarjoaa"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Puhelut, viestit ja data ovat haavoittuvaisempia, kun käytössä on SIM-kortti, jonka <xliff:g id="NETWORK_NAME">%1$s</xliff:g> tarjoaa.\n\nKun yhteys on taas salattu, saat uuden ilmoituksen."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Mobiiliverkkoa koskevat turvallisuusasetukset"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Lue lisää"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"OK"</string>
<string name="fcComplete" msgid="1080909484660507044">"Ominaisuuskoodi valmis."</string>
<string name="fcError" msgid="5325116502080221346">"Yhteysongelma tai virheellinen ominaisuuskoodi."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -371,8 +359,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ota kuvakaappaus"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Voi ottaa kuvakaappauksen näytöstä."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Esikatselu, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"ohita"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"poista tilapalkki käytöstä tai muokkaa tilapalkkia"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Antaa sovelluksen poistaa tilapalkin käytöstä ja lisätä tai poistaa järjestelmäkuvakkeita."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"sijaita tilapalkissa"</string>
@@ -2157,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Ohjelmatilan tietoilmoitus"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Virransäästö päällä"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Akun käyttöä rajoitetaan akunkeston pidentämiseksi"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"Virransäästö on päällä"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"Virransäästö on laitettu päälle akunkeston pidentämiseksi"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Virransäästö"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Virransäästö laitettiin pois päältä"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Puhelimessa on tarpeeksi virtaa. Ominaisuuksia ei enää rajoiteta."</string>
@@ -2231,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Vaihdetaanko työsovellukseen?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Organisaatio sallii soittamisen vain työsovelluksilla"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Organisaatio sallii viestien lähettämisen vain työsovelluksilla"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Voit soittaa puheluita vain henkilökohtaisesta Puhelin-sovelluksesta. Sillä soitetut puhelut lisätään henkilökohtaiseen soittohistoriaasi."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"Voit lähettää tekstiviestejä vain henkilökohtaisesta Messages-sovelluksesta."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Käytä henkilökohtaista selainta"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Käytä työselainta"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Soita"</string>
@@ -2414,8 +2401,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Työ 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Testi"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Jaettu"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Työprofiili"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Yksityinen tila"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Klooni"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Yhteinen"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Arkaluontoisen ilmoituksen sisältö piilotettu"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Sovelluksen sisältö piilotettu näytön jakamiselta turvallisuussyistä"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Yhdistetty automaattisesti satelliittiin"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 749fcf6..dd968e1 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -154,31 +154,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g> : <xliff:g id="DIALING_NUMBER">{1}</xliff:g> au bout de <xliff:g id="TIME_DELAY">{2}</xliff:g> secondes"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g> : non transféré"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g> : non transféré"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Sécurité des réseaux mobiles"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Chiffrement, notifications pour les réseaux non chiffrés"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"Identifiant d\'appareil consulté"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"À <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, un réseau à proximité a enregistré l\'identifiant unique de votre appareil (IMSI ou IIEM) alors que vous utilisiez votre carte SIM <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"À <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, un réseau à proximité a enregistré l\'identifiant unique de votre appareil (IMSI ou IIEM) alors que vous utilisiez votre carte SIM <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>.\n\nCela signifie que votre position, votre activité ou votre identité ont été journalisées. Il s\'agit d\'une pratique courante, mais qui peut poser problème aux personnes soucieuses de leur confidentialité."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Connecté à un réseau chiffré <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"La connexion à la carte SIM <xliff:g id="NETWORK_NAME">%1$s</xliff:g> est maintenant plus sûre"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Connecté à un réseau non chiffré"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Les appels, les messages et les données sont actuellement plus vulnérables lorsque vous utilisez votre carte SIM <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Les appels, les messages et les données sont actuellement plus vulnérables lorsque vous utilisez votre carte SIM <xliff:g id="NETWORK_NAME">%1$s</xliff:g>.\n\nUne fois que votre connexion est à nouveau chiffrée, vous recevez une nouvelle notification."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Paramètres de sécurité du réseau cellulaire"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"En savoir plus"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"OK"</string>
<string name="fcComplete" msgid="1080909484660507044">"Code de service terminé"</string>
<string name="fcError" msgid="5325116502080221346">"Problème de connexion ou code de service non valide"</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -264,7 +252,7 @@
<string name="reboot_safemode_title" msgid="5853949122655346734">"Redémarrer en mode sans échec"</string>
<string name="reboot_safemode_confirm" msgid="1658357874737219624">"Voulez-vous redémarrer en mode sans échec? Cette opération aura pour effet de désactiver toutes les applications tierces que vous avez installées. Elles seront réactivées au prochain redémarrage."</string>
<string name="recent_tasks_title" msgid="8183172372995396653">"Récents"</string>
- <string name="no_recent_tasks" msgid="9063946524312275906">"Aucune application récente"</string>
+ <string name="no_recent_tasks" msgid="9063946524312275906">"Aucune appli récente"</string>
<string name="global_actions" product="tablet" msgid="4412132498517933867">"Options de la tablette"</string>
<string name="global_actions" product="tv" msgid="3871763739487450369">"Options d\'Android TV"</string>
<string name="global_actions" product="default" msgid="6410072189971495460">"Options du téléphone"</string>
@@ -923,7 +911,7 @@
</string-array>
<string name="phoneTypeCustom" msgid="5120365721260686814">"Personnaliser"</string>
<string name="phoneTypeHome" msgid="3880132427643623588">"Domicile"</string>
- <string name="phoneTypeMobile" msgid="1178852541462086735">"Mobile"</string>
+ <string name="phoneTypeMobile" msgid="1178852541462086735">"Cellulaire"</string>
<string name="phoneTypeWork" msgid="6604967163358864607">"Travail"</string>
<string name="phoneTypeFaxWork" msgid="6757519896109439123">"Téléc. travail"</string>
<string name="phoneTypeFaxHome" msgid="6678559953115904345">"Téléc. domicile"</string>
@@ -1250,7 +1238,7 @@
<string name="whichImageCaptureApplicationNamed" msgid="8820702441847612202">"Enregistrer l\'image avec %1$s"</string>
<string name="whichImageCaptureApplicationLabel" msgid="6505433734824988277">"Enregistrer l\'image"</string>
<string name="alwaysUse" msgid="3153558199076112903">"Utiliser cette application par défaut pour cette action"</string>
- <string name="use_a_different_app" msgid="4987790276170972776">"Utiliser une application différente"</string>
+ <string name="use_a_different_app" msgid="4987790276170972776">"Utiliser une appli différente"</string>
<string name="clearDefaultHintMsg" msgid="1325866337702524936">"Pour supprimer les valeurs par défaut, accédez à Paramètres système > Applications > Téléchargements."</string>
<string name="chooseActivity" msgid="8563390197659779956">"Sélectionnez une action"</string>
<string name="chooseUsbActivity" msgid="2096269989990986612">"Sélectionnez une application pour le périphérique de stockage USB"</string>
@@ -2157,6 +2145,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Notification d\'information du mode Routine"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Économiseur de pile activé"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Réduction de l\'utilisation de la pile pour en prolonger l\'autonomie"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"La fonctionnalité Économiseur de pile est activée"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"La fonctionnalité Économiseur de pile est activée pour prolonger l\'autonomie de la pile"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Économiseur de pile"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Le mode Économiseur de pile est désactivé"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Le téléphone est suffisamment chargé. Ces fonctionnalités ne sont plus restreintes."</string>
@@ -2231,10 +2221,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Passer à l\'application professionnelle?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Votre organisation vous autorise à passer des appels uniquement à partir d\'applications professionnelles"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Votre organisation vous autorise à envoyer des messages uniquement à partir d\'applications professionnelles"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Vous ne pouvez passer des appels téléphoniques qu\'à partir de votre application Téléphone personnelle. Les appels passés à l\'aide de cette dernière seront ajoutés à votre historique personnel des appels."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"Vous ne pouvez envoyer des messages texte qu\'à partir de votre appli Messages personnelle."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Utiliser le navigateur du profil personnel"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Utiliser le navigateur du profil professionnel"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Appeler"</string>
@@ -2414,7 +2402,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Professionnel 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Commun"</string>
- <string name="redacted_notification_message" msgid="1520587845842228816">"Le contenu confidentiel des notifications est masqué"</string>
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Profil professionnel"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Espace privé"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Clone"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Commun"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Le contenu confidentiel de la notification est masqué"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Le contenu de l\'application est masqué du Partage d\'écran par mesure de sécurité"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Connecté au satellite automatiquement"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 4e5154e..96636dc 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -154,31 +154,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g> : <xliff:g id="DIALING_NUMBER">{1}</xliff:g> au bout de <xliff:g id="TIME_DELAY">{2}</xliff:g> secondes"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g> : non transféré"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g> : non transféré"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Sécurité du réseau mobile"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Chiffrement, notifications pour les réseaux non chiffrés"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"ID de l\'appareil accessible"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"À <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, un réseau à proximité a enregistré l\'identifiant unique de votre appareil (IMSI ou code IMEI) lors de l\'utilisation de votre carte SIM <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"À <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, un réseau à proximité a enregistré l\'identifiant unique de votre appareil (IMSI ou code IMEI) lors de l\'utilisation de votre carte SIM <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>.\n\nCela signifie que votre localisation, votre activité ou votre identité ont été enregistrées. Il s\'agit d\'une pratique courante, mais qui peut poser problème aux personnes soucieuses du respect de leur confidentialité."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Connecté au réseau chiffré <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"La connexion à la carte SIM <xliff:g id="NETWORK_NAME">%1$s</xliff:g> est désormais plus sécurisée"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Connecté à un réseau non chiffré"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Les appels, les messages et les données sont actuellement plus vulnérables lorsque vous utilisez votre carte SIM <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Les appels, les messages et les données sont actuellement plus vulnérables lorsque vous utilisez votre carte SIM <xliff:g id="NETWORK_NAME">%1$s</xliff:g>.\n\nLorsque votre connexion est à nouveau chiffrée, vous recevez une nouvelle notification."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Paramètres de sécurité du réseau mobile"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"En savoir plus"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"OK"</string>
<string name="fcComplete" msgid="1080909484660507044">"Code de service terminé"</string>
<string name="fcError" msgid="5325116502080221346">"Problème de connexion ou code de service non valide"</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -372,8 +360,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Prendre une capture d\'écran"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Peut prendre des captures d\'écran."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Aperçu, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"ignorer"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"Désactivation ou modification de la barre d\'état"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Permet à l\'application de désactiver la barre d\'état, ou d\'ajouter et de supprimer des icônes système."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"remplacer la barre d\'état"</string>
@@ -2158,6 +2145,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Notification d\'information du mode Routine"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Économiseur de batterie activé"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Réduction de l\'utilisation de la batterie pour prolonger son autonomie"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"Économiseur de batterie activé"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"L\'économiseur de batterie est activé pour prolonger l\'autonomie de la batterie"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Économiseur de batterie"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Économiseur de batterie désactivé"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Téléphone suffisamment chargé. Les fonctionnalités ne sont plus restreintes."</string>
@@ -2232,10 +2221,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Passer à une appli professionnelle ?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Votre organisation ne vous autorise à passer des appels que depuis des applis professionnelles"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Votre organisation ne vous autorise à envoyer des messages que depuis des applis professionnelles"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Vous ne pouvez passer des appels téléphoniques qu\'à partir de votre application personnelle Téléphone. Les appels passés avec cette appli seront ajoutés à votre historique d\'appels personnel."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"Vous ne pouvez envoyer des SMS qu\'à partir de votre application personnelle Messages."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Utiliser le navigateur personnel"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Utiliser le navigateur professionnel"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Appeler"</string>
@@ -2415,8 +2402,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Professionnel 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Commun"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Profil professionnel"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Espace privé"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Clone"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Commun"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Le contenu sensible de la notification a été masqué"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Le contenu de l\'appli est masqué lors du partage d\'écran pour des raisons de sécurité"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Connecté automatiquement au réseau satellite"</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index 2187fed..85ad42f 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> tras <xliff:g id="TIME_DELAY">{2}</xliff:g> segundos"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: non desviada"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: non reenviada"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Seguranza das redes de telefonía móbil"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Encriptación, notificacións para redes non encriptadas"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"Acceso ao código do dispositivo"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"Á/s <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, unha rede próxima rexistrou o código exclusivo (IMSI ou IMEI) do teu dispositivo mentres se usaba a túa SIM de <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"Á/s <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, unha rede próxima rexistrou o código exclusivo (IMSI ou IMEI) do teu dispositivo mentres se usaba a túa SIM de <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>.\n\nIsto significa que se rexistrou a túa localización, actividade ou identidade. Aínda que se trata dunha práctica común, pode supoñer un problema para as persoas ás que lles preocupe a súa privacidade."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Conexión á rede encriptada <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"A conexión coa SIM de <xliff:g id="NETWORK_NAME">%1$s</xliff:g> agora é máis segura"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Conexión a unha rede non encriptada"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Cando usas a SIM de <xliff:g id="NETWORK_NAME">%1$s</xliff:g>, as chamadas, mensaxes e datos son máis vulnerables"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Cando usas a SIM de <xliff:g id="NETWORK_NAME">%1$s</xliff:g>, as chamadas, mensaxes e datos son máis vulnerables.\n\nRecibirás outra notificación cando se volva encriptar a túa conexión."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Configuración de seguranza das redes de telefonía móbil"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Máis información"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"Entendido"</string>
<string name="fcComplete" msgid="1080909484660507044">"Código de función completo"</string>
<string name="fcError" msgid="5325116502080221346">"Problema de conexión ou código de función non válido"</string>
<string name="httpErrorOk" msgid="6206751415788256357">"Aceptar"</string>
@@ -371,8 +359,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Facer captura de pantalla"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Pode facer capturas de pantalla."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Vista previa, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"pechar"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"desactivar ou modificar a barra de estado"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Permite á aplicación desactivar a barra de estado ou engadir e quitar as iconas do sistema."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"actuar como a barra de estado"</string>
@@ -2157,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Notificación da información do modo de rutina"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Activouse Aforro de batería"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Estase limitando o uso da batería para aumentar a súa duración"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"A función Aforro de batería está activada"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"Activouse a función Aforro de batería para prolongar a duración"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Aforro de batería"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Desactivouse a función Aforro de batería."</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"O teléfono non ten suficiente batería. Xa non se restrinxirán as funcións."</string>
@@ -2231,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Queres cambiar á aplicación do traballo?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"A túa organización só che permite chamar desde aplicacións do traballo"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"A túa organización só che permite enviar mensaxes desde aplicacións do traballo"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Só podes facer chamadas telefónicas desde a aplicación Teléfono persoal. Estas chamadas engadiranse ao teu historial de chamadas."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"Só podes enviar SMS desde a aplicación Mensaxes persoal."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Utilizar navegador persoal"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Utilizar navegador de traballo"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Chamar"</string>
@@ -2414,8 +2401,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Traballo 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Proba"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Compartido"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Perfil de traballo"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Espazo privado"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Clonado"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Compartido"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Contido confidencial da notificación oculto"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Por motivos de seguranza, ocultouse o contido da aplicación para que no se mostre na pantalla compartida"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Conexión automática ao satélite"</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index b36b17c..82ffb2f 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="TIME_DELAY">{2}</xliff:g> સેકન્ડ પછી <xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ફોરવર્ડ કર્યો નથી"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ફોરવર્ડ કર્યો નથી"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"મોબાઇલ નેટવર્ક સુરક્ષા"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"એન્ક્રિપ્શન, એન્ક્રિપ્ટ નહીં થયેલા નેટવર્ક માટે નોટિફિકેશન"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"ડિવાઇસ ID ઍક્સેસ કર્યાનો સમય"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"<xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> પર, તમારા <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> સિમ કાર્ડનો ઉપયોગ કરતી વખતે નજીકના કોઈ નેટવર્ક દ્વારા તમારા ડિવાઇસનું અજોડ ID (IMSI અથવા IMEI) રેકોર્ડ કરવામાં આવ્યું હતું"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"<xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> પર, તમારા <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> સિમ કાર્ડનો ઉપયોગ કરતી વખતે નજીકના કોઈ નેટવર્ક દ્વારા તમારા ડિવાઇસનું અજોડ ID (IMSI અથવા IMEI) રેકોર્ડ કરવામાં આવ્યું હતું.\n\nઆનો અર્થ એ છે કે તમારું લોકેશન, ઍક્ટિવિટી અથવા ઓળખ લૉગ કરવામાં આવી છે. આ સામાન્ય પદ્ધતિ છે પરંતુ પ્રાઇવસી વિશે ચિંતિત લોકો માટે સમસ્યા હોઈ શકે છે."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"એન્ક્રિપ્ટેડ નેટવર્ક <xliff:g id="NETWORK_NAME">%1$s</xliff:g> સાથે કનેક્ટેડ છે"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> સિમ કાર્ડ કનેક્શન હવે વધુ સુરક્ષિત છે"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"એન્ક્રિપ્ટ નહીં થયેલા નેટવર્ક સાથે કનેકટેડ છે"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"તમારા <xliff:g id="NETWORK_NAME">%1$s</xliff:g> સિમ કાર્ડનો ઉપયોગ કરતી વખતે કૉલ, મેસેજ અને ડેટા હાલમાં વધુ સંવેદનશીલ છે"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"તમારા <xliff:g id="NETWORK_NAME">%1$s</xliff:g> સિમ કાર્ડનો ઉપયોગ કરતી વખતે કૉલ, મેસેજ અને ડેટા હાલમાં વધુ સંવેદનશીલ છે.\n\nજ્યારે તમારું કનેક્શન ફરીથી એન્ક્રિપ્ટ કરવામાં આવે છે, ત્યારે તમને બીજું નોટિફિકેશન મળશે."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"મોબાઇલ નેટવર્ક સુરક્ષા સંબંધી સેટિંગ"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"વધુ જાણો"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"સમજાઈ ગયું"</string>
<string name="fcComplete" msgid="1080909484660507044">"સુવિધા કોડ પૂર્ણ."</string>
<string name="fcError" msgid="5325116502080221346">"કનેક્શન સમસ્યા અથવા અમાન્ય સુવિધા કોડ."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"ઓકે"</string>
@@ -371,8 +359,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"સ્ક્રીનશૉટ લો"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ડિસ્પ્લેનો સ્ક્રીનશૉટ લઈ શકે છે."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"પ્રીવ્યૂ, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"છોડી દો"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"સ્ટેટસ બારને અક્ષમ કરો અથવા તેમાં ફેરફાર કરો"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"ઍપ્લિકેશનને સ્ટેટસ બાર અક્ષમ કરવાની અથવા સિસ્ટમ આયકન્સ ઉમેરવા અને દૂર કરવાની મંજૂરી આપે છે."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"સ્ટેટસ બારમાં બતાવો"</string>
@@ -2157,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"રૂટિન મોડની માહિતીનું નોટિફિકેશન"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"બૅટરી સેવરની સુવિધા ચાલુ કરી છે"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"બૅટરીની આવરદા વધારવા માટે બૅટરીનો વપરાશ ઘટાડી રહ્યાં છીએ"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"બૅટરી સેવર ચાલુ છે"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"બૅટરીની આવરદા વધારવા માટે, બૅટરી સેવર ચાલુ કરવામાં આવ્યું છે"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"બૅટરી સેવર"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"બૅટરી સેવર બંધ કર્યું"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"ફોનમાં પૂરતો ચાર્જ છે. સુવિધાઓ હવે મર્યાદિત નથી."</string>
@@ -2231,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"શું ઑફિસ માટેની ઍપ પર સ્વિચ કરીએ?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"તમારી સંસ્થા તમને માત્ર ઑફિસ માટેની ઍપ પરથી કૉલ કરવાની મંજૂરી આપે છે"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"તમારી સંસ્થા તમને માત્ર ઑફિસ માટેની ઍપ પરથી મેસેજ મોકલવાની મંજૂરી આપે છે"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"ફક્ત તમે તમારી વ્યક્તિગત ફોન ઍપથી જ ફોન કૉલ કરી શકો છો. વ્યક્તિગત ફોન વડે કરેલા કૉલ તમારા વ્યક્તિગત કૉલ ઇતિહાસમાં ઉમેરવામાં આવશે."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"તમે તમારી વ્યક્તિગત Messages ઍપથી જ SMS મેસેજ મોકલી શકો છો."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"વ્યક્તિગત બ્રાઉઝરનો ઉપયોગ કરો"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"ઑફિસના બ્રાઉઝરના ઉપયોગ કરો"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"કૉલ કરો"</string>
@@ -2414,6 +2401,10 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"ઑફિસ 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"પરીક્ષણ કરો"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"કૉમ્યુનલ"</string>
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"ઑફિસની પ્રોફાઇલ"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"ખાનગી સ્પેસ"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"ક્લોન"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"કૉમ્યુનલ"</string>
<string name="redacted_notification_message" msgid="1520587845842228816">"સંવેદનશીલ માહિતીવાળા નોટિફિકેશનનું કન્ટેન્ટ છુપાવ્યું"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"સુરક્ષા માટે સ્ક્રીન શેર કરતી વખતે ઍપનું કન્ટેન્ટ છુપાવેલું છે"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 40470cd..8772cdc 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> सेकंड के बाद"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: अग्रेषित नहीं किया गया"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: अग्रेषित नहीं किया गया"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"मोबाइल नेटवर्क की सुरक्षा"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"उन नेटवर्क के लिए सुरक्षा से जुड़ी सूचनाएं जो सुरक्षित नहीं हैं"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"डिवाइस आईडी को ऐक्सेस किया गया"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"आपके <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> सिम का इस्तेमाल करके, आस-पास के नेटवर्क ने <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> आपके डिवाइस का यूनीक आईडी (IMSI या IMEI) रिकॉर्ड किया"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"आपका <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> सिम इस्तेमाल करके, आस-पास के नेटवर्क ने <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> आपके डिवाइस का यूनीक आईडी (IMSI या IMEI) रिकॉर्ड किया.\n\nइसका मतलब है कि आपकी जगह की जानकारी, गतिविधि या निजी जानकारी को लॉग इन किया गया है. यह सामान्य तरीका है. हालांकि, यह उन लोगों के लिए समस्या की वजह हो सकता है जिन्हें अपनी निजी जानकारी को लेकर चिंता रहती है."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"एन्क्रिप्ट यानी सुरक्षित नेटवर्क <xliff:g id="NETWORK_NAME">%1$s</xliff:g> से कनेक्ट किया गया"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"अब <xliff:g id="NETWORK_NAME">%1$s</xliff:g> सिम का कनेक्शन ज़्यादा सुरक्षित है"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"ऐसे नेटवर्क से कनेक्ट किया गया जो सुरक्षित नहीं है"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> सिम का इस्तेमाल करने के दौरान, कॉल, मैसेज, और डेटा को ऐक्सेस किए जाने का खतरा हो सकता है"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> सिम का इस्तेमाल करने के दौरान, कॉल, मैसेज, और डेटा को ऐक्सेस किए जाने का खतरा हो सकता है.\n\nजब आपका कनेक्शन फिर से एन्क्रिप्ट यानी सुरक्षित हो जाएगा, तब आपको दोबारा सूचना भेजी जाएगी."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"मोबाइल नेटवर्क की सुरक्षा से जुड़ी सेटिंग"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"ज़्यादा जानें"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"ठीक है"</string>
<string name="fcComplete" msgid="1080909484660507044">"सुविधा कोड पूरा हुआ."</string>
<string name="fcError" msgid="5325116502080221346">"कनेक्शन समस्या या अमान्य सुविधा कोड."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"ठीक है"</string>
@@ -2156,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"रूटीन मोड जानकारी की सूचना"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"बैटरी सेवर चालू है"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"इससे बैटरी कम खर्च होती है और बैटरी लाइफ़ बढ़ती है"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"बैटरी सेवर चालू है"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"बैटरी लाइफ़ बढ़ाने के लिए बैटरी सेवर चालू किया गया है"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"बैटरी सेवर"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"बैटरी सेवर बंद कर दिया गया है"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"फ़ोन में काफ़ी बैटरी बची है. सुविधाओं पर अब पाबंदी नहीं है."</string>
@@ -2230,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"क्या आपको वर्क ऐप्लिकेशन पर स्विच करना है?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"आपके संगठन ने, सिर्फ़ वर्क ऐप्लिकेशन से कॉल करने की अनुमति दी है"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"आपके संगठन ने, सिर्फ़ वर्क ऐप्लिकेशन से मैसेज भेजने की अनुमति दी है"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"सिर्फ़ अपने व्यक्तिगत Phone ऐप्लिकेशन से कॉल किए जा सकते हैं. व्यक्तिगत Phone से किए गए कॉल, व्यक्तिगत कॉल इतिहास में सेव होते हैं."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"सिर्फ़ व्यक्तिगत Messages ऐप्लिकेशन से एसएमएस मैसेज भेजे जा सकते हैं."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"निजी ब्राउज़र का इस्तेमाल करें"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"ऑफ़िस के काम से जुड़े ब्राउज़र का इस्तेमाल करें"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"कॉल करें"</string>
@@ -2413,6 +2401,10 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"ऑफ़िस 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"टेस्ट"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"कम्यूनिटी"</string>
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"वर्क प्रोफ़ाइल"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"प्राइवेट स्पेस"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"क्लोन"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"कम्यूनिटी"</string>
<string name="redacted_notification_message" msgid="1520587845842228816">"संवेदनशील जानकारी वाली सूचना का कॉन्टेंट छिपा है"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"स्क्रीन शेयर करने के दौरान सुरक्षा के लिए, ऐप्लिकेशन का कॉन्टेंट छिपाया गया"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 64f1368..88bc29f 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -154,31 +154,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> nakon <xliff:g id="TIME_DELAY">{2}</xliff:g> s"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nije proslijeđeno"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: nije proslijeđeno"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Sigurnost mobilne mreže"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Šifriranje i obavijesti za nešifrirane mreže"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"Pristupljeno je ID-ju uređaja"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"U <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> mreža u blizini zabilježila je jedinstveni ID (IMSI ili IMEI) vašeg uređaja tijekom upotrebe SIM-a iz mreže <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"U <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> mreža u blizini zabilježila je jedinstveni ID (IMSI ili IMEI) vašeg uređaja tijekom upotrebe SIM-a iz mreže <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>.\n\nTo znači da je vaša lokacija, aktivnost ili identitet zapisan. To je uobičajena praksa, no može predstavljati problem za osobe koje brine privatnost."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Telefon je povezan sa šifriranom mrežom <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"Veza SIM-a s mrežom <xliff:g id="NETWORK_NAME">%1$s</xliff:g> sada je sigurnija"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Uređaj je povezan s nešifriranom mrežom"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Pozivi, poruke i podaci trenutačno su ranjiviji dok se upotrebljava SIM iz mreže <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Pozivi, poruke i podaci trenutačno su ranjiviji dok se upotrebljava SIM iz mreže <xliff:g id="NETWORK_NAME">%1$s</xliff:g>.\n\nKada se vaša veza ponovno šifrira, dobit ćete još jednu obavijest."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Postavke sigurnosti mobilne mreže"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Saznajte više"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"Shvaćam"</string>
<string name="fcComplete" msgid="1080909484660507044">"Kôd značajke je potpun."</string>
<string name="fcError" msgid="5325116502080221346">"Problem s vezom ili nevažeći kôd značajke."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"U redu"</string>
@@ -372,8 +360,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Snimi zaslon"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Možete napraviti snimku zaslona."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Pregled, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"odbaci"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"onemogućavanje ili izmjena trake statusa"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Aplikaciji omogućuje onemogućavanje trake statusa ili dodavanje i uklanjanje sistemskih ikona."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"biti traka statusa"</string>
@@ -1225,7 +1212,7 @@
<string name="rating_label" msgid="1837085249662154601">"{rating,plural, =1{Jedna zvjezdica od {max}}one{# zvjezdica od {max}}few{# zvjezdice od {max}}other{# zvjezdica od {max}}}"</string>
<string name="in_progress" msgid="2149208189184319441">"u tijeku"</string>
<string name="whichApplication" msgid="5432266899591255759">"Radnju dovrši pomoću stavke"</string>
- <string name="whichApplicationNamed" msgid="6969946041713975681">"Dovršavanje radnje pomoću aplikacije %1$s"</string>
+ <string name="whichApplicationNamed" msgid="6969946041713975681">"Dovršite radnju putem aplikacije %1$s"</string>
<string name="whichApplicationLabel" msgid="7852182961472531728">"Dovrši radnju"</string>
<string name="whichViewApplication" msgid="5733194231473132945">"Otvaranje pomoću aplikacije"</string>
<string name="whichViewApplicationNamed" msgid="415164730629690105">"Otvaranje pomoću aplikacije %1$s"</string>
@@ -2158,6 +2145,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Obavještavanje o informacijama u Rutinskom načinu rada"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Uključena je štednja baterije"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Smanjuje se potrošnja baterije radi produženja njezinog trajanja"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"Štednja baterije je uključena"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"Štednja baterije je uključena da bi se produljilo trajanje baterije"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Štednja baterije"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Isključena je Štednja baterije"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Baterija mobilnog telefona dovoljno je napunjena. Značajke više nisu ograničene."</string>
@@ -2232,10 +2221,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Želite li prebaciti na poslovnu aplikaciju?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Vaša organizacija dopušta upućivanje poziva samo iz poslovnih aplikacija"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Vaša organizacija dopušta slanje poruka samo iz poslovnih aplikacija"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Pozive možete upućivati samo iz svoje privatne aplikacije Telefon. Pozivi koji se upućuju iz privatne aplikacije Telefon dodat će se u vašu privatnu povijest poziva."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"SMS poruke možete slati samo iz svoje privatne aplikacije Poruke."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Koristi osobni preglednik"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Koristi poslovni preglednik"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Nazovi"</string>
@@ -2415,8 +2402,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Posao 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Zajedničko"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Radni profil"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Privatni prostor"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Klon"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Zajedničko"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Skriven je osjetljiv sadržaj obavijesti"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Sadržaj aplikacije sakriven je od dijeljenja zaslona radi sigurnosti"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Automatski povezano sa satelitom"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index b4ac675..f7e4a8f 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> másodperc után"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: nincs átirányítva"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: nincs átirányítva"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Mobilhálózati biztonság"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Titkosítás, értesítés titkosítás nélküli hálózatok esetén"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"Hozzáférés az eszközazonosítóhoz"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"A következő időpontban egy közeli hálózat észlelte az Ön eszközének egyedi azonosítóját (IMSI vagy IMEI), miközben az eszköz az Ön <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>-SIM-jét használta: <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>."</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"A következő időpontban egy közeli hálózat rögzítette az Ön eszközének egyedi azonosítóját (IMSI vagy IMEI), miközben az eszköz az Ön <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>-SIM-jét használta: <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>.\n\nEz azt jelenti, hogy az Ön tartózkodási helye, tevékenysége és személyazonossága naplózásra került. Ez bevett gyakorlat, de problémát jelenthet az adatvédelem miatt aggódó személyek számára."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"A következő titkosított hálózathoz csatlakozik: <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"A(z) <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM-kapcsolata mostantól biztonságosabb"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Nem titkosított hálózathoz csatlakozik"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"A hívások, az SMS-ek és az adatforgalom jelenleg sebezhetőbbek, amíg <xliff:g id="NETWORK_NAME">%1$s</xliff:g>-SIM-jét használja."</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"A hívások, az SMS-ek és az adatforgalom jelenleg sebezhetőbbek, amíg <xliff:g id="NETWORK_NAME">%1$s</xliff:g>-SIM-jét használja.\n\nAmint hálózata újra titkosított lesz, újabb értesítést fog kapni."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"A mobilhálózati biztonság beállításai"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"További információ"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"Értem"</string>
<string name="fcComplete" msgid="1080909484660507044">"A funkciókód kész."</string>
<string name="fcError" msgid="5325116502080221346">"Kapcsolódási probléma vagy érvénytelen funkciókód."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -371,8 +359,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Képernyőkép készítése"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Készíthet képernyőképet a kijelzőről."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Előnézet, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"elvetés"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"állapotsor kikapcsolása vagy módosítása"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Lehetővé teszi az alkalmazás számára az állapotsor kikapcsolását, illetve rendszerikonok hozzáadását és eltávolítását."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"az állapotsor szerepének átvétele"</string>
@@ -2157,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Információs értesítés a rutinmódról"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Akkumulátorkímélő mód bekapcsolva"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Akkuhasználat csökkentése a hosszabb akkumulátor-élettartam érdekében"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"Akkumulátorkímélő mód bekapcsolva"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"Az akkumulátor-üzemidő meghosszabbítása érdekében bekapcsolódott az Akkumulátorkímélő mód"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Akkumulátorkímélő mód"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Akkumulátorkímélő mód kikapcsolva"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"A telefon töltöttsége elegendő. A funkciók használata már nincs korlátozva."</string>
@@ -2231,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Átvált a munkahelyi alkalmazásra?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Szervezete csak munkahelyi alkalmazásokból engedélyezi a hívásindítást"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Szervezete csak munkahelyi alkalmazásokból engedélyezi az üzenetküldést"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Csak az Ön személyes Telefon alkalmazásából indíthat hívásokat. A személyes Telefon alkalmazással indított hívásokat hozzáadja a rendszer az Ön személyes híváslistájához."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"Csak az Ön személyes Messages alkalmazásából küldhet SMS-eket."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Személyes böngésző használata"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Munkahelyi böngésző használata"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Hívás"</string>
@@ -2414,8 +2401,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"3. munkahelyi"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Teszt"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Közös"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Munkaprofil"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Privát terület"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Klón"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Közös"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Bizalmas értesítéstartalom elrejtve"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"A biztonság érdekében a képernyőmegosztástól elrejtett alkalmazástartalom"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Automatikusan csatlakozva a műholdhoz"</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 609810a..251646c 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>. <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> վայրկյանից"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>. Չի վերահասցեավորվել"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>. Չի վերահասցեավորվել"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Ցանցային անվտանգություն"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Գաղտնագրում, ծանուցումներ չգաղտնագրված ցանցերի համար"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"Սարքի նույնացույցիչը հասանելի է դարձել"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"Ժամը <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>-ին մոտակա ցանցը գրանցել է ձեր սարքի եզակի նույնացուցիչը (IMSI-ը կամ IMEI-ը) <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>-ի ձեր SIM քարտի օգտագործման ժամանակ"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"Ժամը <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>-ին մոտակա ցանցը գրանցել է ձեր սարքի եզակի նույնացուցիչը (IMSI-ը կամ IMEI-ը) <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>-ի ձեր SIM քարտի օգտագործման ժամանակ։\n\nԴա նշանակում է, որ ձեր տեղադրությունը, գործողությունները կամ անձը նույնականացնող տվյալները գրանցվել են։ Սա սովորական գործելակերպ է, սակայն կարող է խնդիր լինել այն մարդկանց համար, որոնք մտահոգված են իրենց գաղտնիությամբ։"</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Հեռախոսը միացավ <xliff:g id="NETWORK_NAME">%1$s</xliff:g> գաղտնագրված ցանցին"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>-ի SIM քարտի միացումն այժմ ավելի անվտանգ է"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Միացած է չգաղտնագրված ցանցի"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Զանգերը, հաղորդագրությունները և տվյալները ներկայումս ավելի խոցելի են <xliff:g id="NETWORK_NAME">%1$s</xliff:g>-ի ձեր SIM քարտի օգտագործման ժամանակ"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Զանգերը, հաղորդագրությունները և տվյալները ներկայումս ավելի խոցելի են <xliff:g id="NETWORK_NAME">%1$s</xliff:g>-ի ձեր SIM քարտի օգտագործման ժամանակ։\n\nԵրբ ձեր կապը նորից գաղտնագրվի, դուք կստանաք մեկ այլ ծանուցում։"</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Ցանցային անվտանգության կարգավորումներ"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Իմանալ ավելին"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"Եղավ"</string>
<string name="fcComplete" msgid="1080909484660507044">"Հատկության կոդը ամբողջական է:"</string>
<string name="fcError" msgid="5325116502080221346">"Կապի խնդիր կամ անվավեր գործառույթի կոդ:"</string>
<string name="httpErrorOk" msgid="6206751415788256357">"Եղավ"</string>
@@ -371,8 +359,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Սքրինշոթի ստեղծում"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Կարող է ստեղծել էկրանի սքրինշոթ։"</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Նախադիտում, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"փակել"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"անջատել կամ փոփոխել կարգավիճակի գոտին"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Թույլ է տալիս հավելվածին անջատել կարգավիճակի գոտին կամ ավելացնել ու հեռացնել համակարգի պատկերակները:"</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"լինել կարգավիճակի գոտի"</string>
@@ -1224,7 +1211,7 @@
<string name="rating_label" msgid="1837085249662154601">"{rating,plural, =1{Մեկ աստղ՝ {max}-ից}one{# աստղ՝ {max}-ից}other{# աստղ՝ {max}-ից}}"</string>
<string name="in_progress" msgid="2149208189184319441">"ընթացքում է"</string>
<string name="whichApplication" msgid="5432266899591255759">"Ավարտել գործողությունը` օգտագործելով"</string>
- <string name="whichApplicationNamed" msgid="6969946041713975681">"Եզրափակել գործողությունը՝ օգտագործելով %1$s"</string>
+ <string name="whichApplicationNamed" msgid="6969946041713975681">"Կատարել՝ օգտագործելով %1$s"</string>
<string name="whichApplicationLabel" msgid="7852182961472531728">"Ավարտել գործողությունը"</string>
<string name="whichViewApplication" msgid="5733194231473132945">"Բացել հետևյալ ծրագրով՝"</string>
<string name="whichViewApplicationNamed" msgid="415164730629690105">"Բացել հավելվածով՝ %1$s"</string>
@@ -2157,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Ծանուցում լիցքավորման մասին"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Մարտկոցի տնտեսումը միացվել է"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Մարտկոցի օգտագործումը նվազեցվել է դրա աշխատաժամանակը երկարացնելու համար"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"Մարտկոցի տնտեսումը միացված է"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"Մարտկոցի տնտեսումը միացվել է՝ մարտկոցի աշխատաժամանակը երկարացնելու համար"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Մարտկոցի տնտեսում"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Մարտկոցի տնտեսումն անջատված է"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Հեռախոսի լիցքը բավարար է։ Գործառույթներն այլևս չեն սահմանափակվում։"</string>
@@ -2231,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Անցնե՞լ աշխատանքային հավելվածի"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Ձեր կազմակերպությունը թույլատրում է ձեզ զանգեր կատարել միայն աշխատանքային հավելվածներից"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Ձեր կազմակերպությունը թույլատրում է ձեզ հաղորդագրություններ ուղարկել միայն աշխատանքային հավելվածներից"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Դուք կարող եք զանգահարել միայն ձեր անձնական «Հեռախոս» հավելվածից։ Անձնական «Հեռախոս» հավելվածով կատարված զանգերը կավելացվեն ձեր անձնական զանգերի պատմության մեջ։"</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"Դուք կարող եք SMS հաղորդագրություններ ուղարկել միայն ձեր անձնական Messages հավելվածից։"</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Օգտագործել անձնական դիտարկիչը"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Օգտագործել աշխատանքային դիտարկիչը"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Զանգել"</string>
@@ -2414,8 +2401,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Աշխատանքային 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Փորձնական"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Ընդհանուր"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Աշխատանքային պրոֆիլ"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Մասնավոր տարածք"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Կլոն"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Ընդհանուր"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Ծանուցման զգայուն բովանդակությունը թաքցված է"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Անվտանգության նկատառումներից ելնելով՝ հավելվածի բովանդակությունը թաքցվել է էկրանի ցուցադրումից"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Ավտոմատ միացել է արբանյակին"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 1956c92..139b4ab 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> setelah <xliff:g id="TIME_DELAY">{2}</xliff:g> detik"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Tidak diteruskan"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Tidak diteruskan"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Keamanan jaringan seluler"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Enkripsi, notifikasi untuk jaringan yang tidak terenkripsi"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"ID perangkat diakses"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"Pada <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, jaringan di sekitar merekam ID unik perangkat Anda (IMSI atau IMEI) saat menggunakan kartu SIM <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> Anda"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"Pada <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, jaringan di sekitar merekam ID unik perangkat Anda (IMSI atau IMEI) saat menggunakan kartu SIM <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> Anda.\n\nHal ini berarti lokasi, aktifitas, atau identitas Anda telah dicatat dalam log. Tindakan ini adalah praktik umum tetapi dapat menjadi masalah bagi orang yang mengkhawatirkan privasi."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Terhubung ke jaringan yang terenkripsi <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"Koneksi kartu SIM <xliff:g id="NETWORK_NAME">%1$s</xliff:g> kini lebih aman"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Terhubung ke jaringan yang tidak terenkripsi"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Panggilan, pesan, dan data saat ini lebih rentan saat menggunakan kartu SIM <xliff:g id="NETWORK_NAME">%1$s</xliff:g> Anda"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Panggilan, pesan, dan data saat ini lebih rentan saat menggunakan kartu SIM <xliff:g id="NETWORK_NAME">%1$s</xliff:g> Anda.\n\nKetika koneksi Anda terenkripsi lagi, Anda akan menerima notifikasi lainnya."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Setelan keamanan jaringan seluler"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Pelajari lebih lanjut"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"Oke"</string>
<string name="fcComplete" msgid="1080909484660507044">"Kode fitur selesai."</string>
<string name="fcError" msgid="5325116502080221346">"Masalah sambungan atau kode fitur tidak valid."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"Oke"</string>
@@ -371,8 +359,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ambil screenshot"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Dapat mengambil screenshot tampilan."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Pratinjau, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"tutup"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"nonaktifkan atau ubah bilah status"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Mengizinkan apl menonaktifkan bilah status atau menambah dan menghapus ikon sistem."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"jadikan bilah status"</string>
@@ -1250,7 +1237,7 @@
<string name="whichImageCaptureApplicationNamed" msgid="8820702441847612202">"Jepret gambar dengan %1$s"</string>
<string name="whichImageCaptureApplicationLabel" msgid="6505433734824988277">"Jepret gambar"</string>
<string name="alwaysUse" msgid="3153558199076112903">"Gunakan secara default untuk tindakan ini."</string>
- <string name="use_a_different_app" msgid="4987790276170972776">"Gunakan aplikasi yang berbeda"</string>
+ <string name="use_a_different_app" msgid="4987790276170972776">"Gunakan aplikasi lain"</string>
<string name="clearDefaultHintMsg" msgid="1325866337702524936">"Menghapus default di Setelan sistem > Apl > Terdownload."</string>
<string name="chooseActivity" msgid="8563390197659779956">"Pilih tindakan"</string>
<string name="chooseUsbActivity" msgid="2096269989990986612">"Pilih apl untuk perangkat USB"</string>
@@ -2157,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Notifikasi info Mode Rutinitas"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Penghemat Baterai diaktifkan"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Mengurangi penggunaan baterai untuk memperpanjang masa pakai baterai"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"Penghemat Baterai aktif"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"Penghemat Baterai diaktifkan untuk memperpanjang daya tahan baterai"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Penghemat Baterai"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Penghemat Baterai dinonaktifkan"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Baterai ponsel cukup terisi. Fitur tidak lagi dibatasi."</string>
@@ -2231,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Beralih ke aplikasi kerja?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Organisasi Anda hanya mengizinkan menelepon dari aplikasi kerja"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Organisasi Anda hanya mengizinkan pengiriman pesan dari aplikasi kerja"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Anda hanya dapat melakukan panggilan telepon dari aplikasi Telepon pribadi. Panggilan yang dilakukan dengan aplikasi Telepon pribadi akan ditambahkan ke histori panggilan pribadi."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"Anda hanya dapat mengirim pesan SMS dari aplikasi Message pribadi."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Gunakan browser pribadi"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Gunakan browser kerja"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Telepon"</string>
@@ -2407,13 +2394,17 @@
<string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Tata letak keyboard disetel ke <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… Ketuk untuk mengubah."</string>
<string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Keyboard fisik telah dikonfigurasi"</string>
<string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Ketuk untuk melihat keyboard"</string>
- <string name="profile_label_private" msgid="6463418670715290696">"Pribadi"</string>
+ <string name="profile_label_private" msgid="6463418670715290696">"Privasi"</string>
<string name="profile_label_clone" msgid="769106052210954285">"Clone"</string>
<string name="profile_label_work" msgid="3495359133038584618">"Kerja"</string>
<string name="profile_label_work_2" msgid="4691533661598632135">"Kerja 2"</string>
<string name="profile_label_work_3" msgid="4834572253956798917">"Kerja 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Pengujian"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Umum"</string>
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Profil kerja"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Ruang privasi"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Clone"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Umum"</string>
<string name="redacted_notification_message" msgid="1520587845842228816">"Konten notifikasi sensitif disembunyikan"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Konten aplikasi disembunyikan dari berbagi layar untuk alasan keamanan"</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index 2a02c0c..1f55241 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> eftir <xliff:g id="TIME_DELAY">{2}</xliff:g> sekúndur"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Ekki áframsent"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Ekki áframsent"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Öryggi farsímakerfis"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Dulkóðun og tilkynningar um ódulkóðuð netkerfi"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"Auðkenni tækis opnað"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"Klukkan <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> skráði nálægt netkerfi einkvæmt auðkenni tækisins þíns (IMSI eða IMEI) með því að nota tengingu SIM-kortsins þíns við <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>."</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"Klukkan <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> skráði nálægt netkerfi einkvæmt auðkenni tækisins þíns (IMSI eða IMEI) með því að nota tengingu SIM-kortsins þíns við <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>.\n\nÞað þýðir að staðsetningin þín, virkni eða auðkenni hefur verið skráð. Þetta er algengt verklag en kann að valda fólki áhyggjum sem er annt um persónuvernd sína."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Þú ert með tengingu við dulkóðaða netkerfið „<xliff:g id="NETWORK_NAME">%1$s</xliff:g>“"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"Tenging SIM-kortsins við <xliff:g id="NETWORK_NAME">%1$s</xliff:g> er nú öruggari"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Þú ert með tengingu við ódulkóðað netkerfi"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Símtöl, skilaboð og gögn eru nú berskjaldaðri þegar þú notar SIM-kortið sem er tengt við <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Símtöl, skilaboð og gögn eru nú berskjaldaðri þegar þú notar SIM-kortið sem er tengt við <xliff:g id="NETWORK_NAME">%1$s</xliff:g>.\n\nÞú færð aðra tilkynningu þegar tengingin verður dulkóðuð á ný."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Öryggisstillingar farsímakerfis"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Nánar"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"Ég skil"</string>
<string name="fcComplete" msgid="1080909484660507044">"Kóðaskipun framkvæmd."</string>
<string name="fcError" msgid="5325116502080221346">"Vandamál með tengingu eða ógild kóðaskipun."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"Í lagi"</string>
@@ -371,8 +359,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Taka skjámynd"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Getur tekið skjámynd af skjánum."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Forskoðun, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"hunsa"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"slökkva á eða breyta stöðustiku"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Leyfir forriti að slökkva á stöðustikunni eða bæta við og fjarlægja kerfistákn."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"vera stöðustikan"</string>
@@ -1018,8 +1005,8 @@
<string name="lockscreen_missing_sim_message" product="tablet" msgid="3986843848305639161">"Það er ekkert SIM-kort í spjaldtölvunni."</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="3903140876952198273">"Það er ekkert SIM-kort í Android TV-tækinu."</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="6184187634180854181">"Það er ekkert SIM-kort í símanum."</string>
- <string name="lockscreen_missing_sim_instructions" msgid="5823469004536805423">"Bæta við SIM-korti."</string>
- <string name="lockscreen_missing_sim_instructions_long" msgid="4403843937236648032">"SIM-kort vantar eða er ekki læsilegt. Bæta við SIM-korti."</string>
+ <string name="lockscreen_missing_sim_instructions" msgid="5823469004536805423">"Bæta SIM-korti við."</string>
+ <string name="lockscreen_missing_sim_instructions_long" msgid="4403843937236648032">"SIM-kort vantar eða er ekki læsilegt. Bæta SIM-korti við."</string>
<string name="lockscreen_permanent_disabled_sim_message_short" msgid="1925200607820809677">"Ónothæft SIM-kort."</string>
<string name="lockscreen_permanent_disabled_sim_instructions" msgid="6902979937802238429">"SIM-kortið þitt var gert varanlega óvirkt.\n Hafðu samband við símafyrirtækið þitt til að fá nýtt SIM-kort."</string>
<string name="lockscreen_transport_prev_description" msgid="2879469521751181478">"Fyrra lag"</string>
@@ -2157,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Upplýsingatilkynning aðgerðastillingar"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Kveikt á rafhlöðusparnaði"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Dregur úr rafhlöðunotkun til að auka endingu rafhlöðunnar"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"Kveikt er á rafhlöðusparnaði"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"Kveikt er á rafhlöðusparnaði til að lengja rafhlöðuendingu"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Rafhlöðusparnaður"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Slökkt á rafhlöðusparnaði"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Síminn er með næga hleðslu. Eiginleikar eru ekki lengur takmarkaðir."</string>
@@ -2231,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Skipta yfir í vinnuforrit?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Fyrirtækið heimilar þér aðeins að hringja úr vinnuforritum"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Fyrirtækið heimilar þér aðeins að senda skilaboð úr vinnuforritum"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Þú getur eingöngu hringt símtöl úr þínu persónulega símaforriti. Símtölum úr persónulegu símaforriti verður bætt við þinn persónulega símtalaferil."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"Þú getur eingöngu sent SMS-skilaboð úr þínu persónulega skilaboðaforriti."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Nota einkavafra"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Nota vinnuvafra"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Hringja"</string>
@@ -2414,8 +2401,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Vinna 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Prófun"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Sameiginlegt"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Vinnusnið"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Leynirými"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Afrit"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Sameiginlegt"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Viðkvæmt tilkynningaefni falið"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Efni forrits falið í skjádeilingu af öryggisástæðum"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Tengdist sjálfkrafa við gervihnött"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index b943073..2f066b5 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -154,31 +154,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g><xliff:g id="DIALING_NUMBER">{1}</xliff:g> dopo <xliff:g id="TIME_DELAY">{2}</xliff:g> secondi"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: inoltro non effettuato"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: inoltro non effettuato"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Sicurezza di rete mobile"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Crittografia, notifiche per reti non criptate"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"È stato eseguito un accesso all\'ID dispositivo"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"Alle ore <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> una rete nelle vicinanze ha registrato l\'ID univoco (IMSI o IMEI) del tuo dispositivo mentre era in uso la tua SIM <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"Alle ore <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> una rete nelle vicinanze ha registrato l\'ID univoco (IMSI o IMEI) del tuo dispositivo mentre era in uso la tua SIM <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>.\n\nQuesto significa che la tua posizione, attività o identità è stata registrata. Si tratta di una prassi comune, ma potrebbe rappresentare un problema per le persone preoccupate riguardo alla privacy."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Connesso alla rete criptata <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"La connessione della SIM <xliff:g id="NETWORK_NAME">%1$s</xliff:g> ora è più sicura"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Connesso a una rete non criptata"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Chiamate, messaggi e dati al momento sono più vulnerabili quando usi la tua SIM <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Chiamate, messaggi e dati al momento sono più vulnerabili quando usi la tua SIM <xliff:g id="NETWORK_NAME">%1$s</xliff:g>.\n\nQuando la tua connessione sarà nuovamente criptata, riceverai un\'altra notifica."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Impostazioni della sicurezza di rete mobile"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Scopri di più"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"Ok"</string>
<string name="fcComplete" msgid="1080909484660507044">"Codice funzione completo."</string>
<string name="fcError" msgid="5325116502080221346">"Problema di connessione o codice funzione non valido."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -372,8 +360,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Acquisire screenshot"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Può acquisire uno screenshot del display."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"<xliff:g id="DREAM_NAME">%1$s</xliff:g> in anteprima"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"chiudi"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"disattivazione o modifica della barra di stato"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Consente all\'applicazione di disattivare la barra di stato o di aggiungere e rimuovere icone di sistema."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"ruolo di barra di stato"</string>
@@ -1225,7 +1212,7 @@
<string name="rating_label" msgid="1837085249662154601">"{rating,plural, =1{Una stella su {max}}many{# stelle su {max}}other{# stelle su {max}}}"</string>
<string name="in_progress" msgid="2149208189184319441">"In corso"</string>
<string name="whichApplication" msgid="5432266899591255759">"Completa l\'azione con"</string>
- <string name="whichApplicationNamed" msgid="6969946041713975681">"Completamento azione con %1$s"</string>
+ <string name="whichApplicationNamed" msgid="6969946041713975681">"Completa l\'azione con %1$s"</string>
<string name="whichApplicationLabel" msgid="7852182961472531728">"Completa azione"</string>
<string name="whichViewApplication" msgid="5733194231473132945">"Apri con"</string>
<string name="whichViewApplicationNamed" msgid="415164730629690105">"Apri con %1$s"</string>
@@ -2158,6 +2145,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Notifica di informazioni sulla modalità Routine"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Risparmio energetico attivato"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Riduzione dell\'utilizzo di batteria per estenderne la durata"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"Risparmio energetico attivo"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"Risparmio energetico è attivo per aumentare la durata della batteria"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Risparmio energetico"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Risparmio energetico disattivato"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Il telefono ha carica sufficiente. Funzionalità non più limitate."</string>
@@ -2232,10 +2221,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Vuoi passare all\'app di lavoro?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"La tua organizzazione consente di fare chiamate solo dalle app di lavoro"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"La tua organizzazione consente di inviare messaggi solo dalle app di lavoro"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Puoi effettuare chiamate solo dalla tua app Telefono personale. Le chiamate effettuate con la tua app Telefono personale verranno aggiunte alla tua cronologia chiamate personale."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"Puoi inviare messaggi SMS solo dalla tua app Messaggi personale."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Usa il browser personale"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Usa il browser di lavoro"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Chiama"</string>
@@ -2415,8 +2402,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Lavoro 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Condiviso"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Profilo di lavoro"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Spazio privato"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Clone"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Condiviso"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Contenuti sensibili della notifica nascosti"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Contenuti dell\'app nascosti dalla condivisione schermo per sicurezza"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Connessione automatica al satellite"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 62ed6fc..3fc962a 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -154,31 +154,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> אחרי <xliff:g id="TIME_DELAY">{2}</xliff:g> שניות"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ללא העברה"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ללא העברה"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"אבטחת הרשת הסלולרית"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"הצפנה, התראות על רשתות לא מוצפנות"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"בוצעה גישה למזהה המכשיר"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"בשעה <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, רשת קרובה רשמה את המזהה הייחודי של המכשיר שלך (IMSI או IMEI) בזמן השימוש בכרטיס ה-SIM של <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"בשעה <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, רשת קרובה רשמה את המזהה הייחודי של המכשיר שלך (IMSI או IMEI) בזמן השימוש בכרטיס ה-SIM של <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>.\n\nמשמעות הדבר היא שהמיקום, הפעילות או הזהות שלך נרשמו. זוהי פעולה שגרתית, אך היא עשויה להוות בעיה לאנשים שמודאגים לגבי פרטיות."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"יש חיבור לרשת המוצפנת <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"החיבור של כרטיס ה-SIM של <xliff:g id="NETWORK_NAME">%1$s</xliff:g> מאובטח יותר עכשיו"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"יש חיבור לרשת לא מוצפנת"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"השיחות, ההודעות והנתונים שלך פגיעים יותר עכשיו בזמן השימוש בכרטיס ה-SIM של <xliff:g id="NETWORK_NAME">%1$s</xliff:g> שלך"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"שיחות, הודעות ונתונים פגיעים יותר עכשיו בזמן השימוש בכרטיס ה-SIM של <xliff:g id="NETWORK_NAME">%1$s</xliff:g> שלך.\n\nכשהחיבור שלך יוצפן שוב, תישלח אליך התראה נוספת."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"הגדרות אבטחה של רשת סלולרית"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"מידע נוסף"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"הבנתי"</string>
<string name="fcComplete" msgid="1080909484660507044">"קוד תכונה הושלם."</string>
<string name="fcError" msgid="5325116502080221346">"בעיה בחיבור או קוד תכונה לא תקין."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"אישור"</string>
@@ -2157,6 +2145,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"התראת מידע לגבי מצב שגרתי"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"התכונה \'חיסכון בסוללה\' הופעלה"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"הפחתת השימוש בסוללה תאריך את חיי הסוללה"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"החיסכון בסוללה מופעל"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"מצב \'חיסכון בסוללה\' מופעל כדי להאריך את חיי הסוללה"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"חיסכון בסוללה"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"מצב \'חיסכון בסוללה\' כבוי"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"הטלפון טעון מספיק. התכונות כבר לא מוגבלות."</string>
@@ -2231,10 +2221,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"לעבור לאפליקציה לעבודה?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"בארגון שלך מאפשרים לבצע שיחות רק מאפליקציות לעבודה"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"בארגון שלך מאפשרים לשלוח הודעות רק מאפליקציות לעבודה"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"ניתן לבצע שיחות טלפון רק מאפליקציית הטלפון האישית שלך. שיחות שיבוצעו באמצעות הטלפון האישי יתווספו להיסטוריית השיחות האישית שלך."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"אפשר לשלוח הודעות SMS רק מאפליקציית ההודעות האישית שלך."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"בדפדפן האישי"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"בדפדפן של העבודה"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"שיחה"</string>
@@ -2414,8 +2402,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"פרופיל עבודה 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"בדיקה"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"שיתופי"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"פרופיל העבודה"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"המרחב הפרטי"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"שכפול"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"שיתופי"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"יש תוכן רגיש בהתראה שהוסתר"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"תוכן האפליקציה מוסתר משיתוף המסך מטעמי אבטחה"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"חיבור אוטומטי ללוויין"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 61eb776..db3ba5a 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:<xliff:g id="DIALING_NUMBER">{1}</xliff:g> (<xliff:g id="TIME_DELAY">{2}</xliff:g>秒後)"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:転送できません"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:転送できません"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"モバイル ネットワーク セキュリティ"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"暗号化(ネットワークが暗号化されていない場合に通知)"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"デバイス ID へのアクセスが発生しました"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"<xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>、<xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> の SIM の使用中に付近のネットワークでお使いのデバイスの一意の ID(IMSI または IMEI)が記録されました"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"<xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>、<xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> の SIM の使用中に付近のネットワークでお使いのデバイスの一意の ID(IMSI または IMEI)が記録されました。\n\nつまり、あなたの位置情報、アクティビティ、身元などが記録されことになります。これはよくある事象ですが、プライバシーに不安を持たれている人にとっては問題になる可能性があります。"</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"暗号化されたネットワーク(<xliff:g id="NETWORK_NAME">%1$s</xliff:g>)に接続しました"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> の SIM 接続のセキュリティが強化されました"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"接続先のネットワークが暗号化されていません"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"現在、通話、メッセージ、データは、<xliff:g id="NETWORK_NAME">%1$s</xliff:g> の SIM の使用中に脆弱性が高くなっています"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"現在、通話、メッセージ、データは、<xliff:g id="NETWORK_NAME">%1$s</xliff:g> の SIM の使用中に脆弱性が高くなっています。\n\n接続が再び暗号化されましたら、改めてお知らせします。"</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"モバイル ネットワーク セキュリティの設定"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"詳細"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"OK"</string>
<string name="fcComplete" msgid="1080909484660507044">"機能コードが完了しました。"</string>
<string name="fcError" msgid="5325116502080221346">"接続エラーまたは無効な機能コードです。"</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -2156,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"ルーティン モード情報の通知"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"バッテリー セーバーが ON になりました"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"バッテリー使用量を減らし、バッテリー駆動時間を延ばします"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"バッテリー セーバーが ON になっています"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"バッテリーを長持ちさせるためにバッテリー セーバーが ON になっています"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"バッテリー セーバー"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"バッテリー セーバーが OFF になりました"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"スマートフォンが十分に充電されました。機能は制限されなくなりました。"</string>
@@ -2230,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"仕事用アプリに切り替えますか?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"組織では、仕事用アプリからの通話のみ許可されています"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"組織では、仕事用アプリからのメッセージ送信のみ許可されています"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"電話は個人用の電話アプリからのみかけることができます。個人用の電話アプリを使った通話は、個人用の通話履歴に追加されます。"</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"SMS メッセージは個人用のメッセージ アプリからのみ送信できます。"</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"個人用ブラウザを使用"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"仕事用ブラウザを使用"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"通話"</string>
@@ -2413,6 +2401,10 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"仕事用 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"テスト"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"共用"</string>
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"仕事用プロファイル"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"プライベート スペース"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"複製"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"共用"</string>
<string name="redacted_notification_message" msgid="1520587845842228816">"プライベートな通知内容は表示されません"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"セキュリティ上、画面共有ではアプリの内容は非表示となります"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index 2beae01..97003c4 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> წამის შემდეგ"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: არ არის გადამისამართებული"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: არ არის გადამისამართებული"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"მობილური ქსელის უსაფრთხოება"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"დაშიფვრა, შეტყობინებები დაუშიფრავი ქსელებისთვის"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"მოწყობილობის ID გაზიარებულია"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"<xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> საათზე ახლომდებარე ქსელმა ჩაიწერა თქვენი მოწყობილობის უნიკალური ID (IMSI ან IMEI) თქვენი <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> SIM-ბარათით სარგებლობისას."</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"<xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> საათზე ახლომდებარე ქსელმა ჩაიწერა თქვენი მოწყობილობის უნიკალური ID (IMSI ან IMEI), თქვენი <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> SIM-ბარათით სარგებლობისას.\n\nეს ნიშნავს, რომ თქვენი მდებარეობა, აქტივობა ან ვინაობა დამახსოვრებულია ჟურნალში. ეს გავრცელებული პრაქტიკაა, თუმცა შესაძლოა კონფიდენციალურობის მსურველი პირებისთვის პრობლემა იყოს."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"დაკავშირებულია დაშიფრულ ქსელთან <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM-ბარათის კავშირი ახლა ბევრად უსაფრთხო გახდა"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"დაკავშირებულია დაუშიფრავ ქსელთან"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"ზარები, შეტყობინებები და მონაცემები ამჟამად უფრო მოწყვლადია თქვენი <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM-ბარათით სარგებლობისას"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"ზარები, შეტყობინებები და მონაცემები ამჟამად უფრო მოწყვლადია <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM-ბარათით სარგებლობისას.\n\nკავშირის ხელახლა დაშიფვრის შემთხვევაში კიდევ ერთ შეტყობინებას მიიღებთ."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"მობილური ქსელის უსაფრთოების პარამეტრები"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"შეიტყვეთ მეტი"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"გასაგებია"</string>
<string name="fcComplete" msgid="1080909484660507044">"ფუნქციის კოდი შესრულდა."</string>
<string name="fcError" msgid="5325116502080221346">"კავშირის პრობლემაა ან არასწორი ფუნქციური კოდია."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"კარგი"</string>
@@ -371,8 +359,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ეკრანის ანაბეჭდის გადაღება"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"შეუძლია ეკრანის ანაბეჭდის გადაღება."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"გადახედვა, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"დახურვა"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"სტატუსის ზოლის გათიშვა ან ცვლილება"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"აპს შეეძლება სტატუსების ზოლის გათიშვა და სისტემის ხატულების დამატება/წაშლა."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"სტატუსის ზოლის ჩანაცვლება"</string>
@@ -2157,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"რუტინის რეჟიმის საინფორმაციო შეტყობინება"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"ბატარეის დამზოგველი ჩართულია"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"ბატარეის მოხმარების შემცირება ბატარეის მუშაობის გახანგრძლივების მიზნით"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"ბატარეის დამზოგი ჩართულია"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"ბატარეის მუშაობის გასახანგრძლივებლად ჩართულია ბატარეის დამზოგი"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"ბატარეის დამზოგი"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"ბატარეის დამზოგი გამორთულია"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"ტელეფონი საკმარისად არის დატენილი. ფუნქციები შეზღუდული აღარ არის."</string>
@@ -2231,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"გადაერთვებით სამუშაო აპზე?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"თქვენი ორგანიზაცია ნებას გრთავთ, რომ დარეკოთ მხოლოდ სამსახურის აპებიდან"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"თქვენი ორგანიზაცია ნებას გრთავთ, მხოლოდ სამსახურის აპებიდან გაგზავნოთ შეტყობინებები"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"სატელეფონო ზარების განხორციელება მხოლოდ თქვენი პირადი ტელეფონის აპიდან შეგიძლიათ. პირადი ტელეფონიდან განხორციელებული ზარები დაემატება პირადი საუბრის ისტორიაში."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"SMS შეტყობინებების გაგზავნა მხოლოდ თქვენი პირადი შეტყობინებების აპიდან შეგიძლიათ."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"პირადი ბრაუზერის გამოყენება"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"სამსახურის ბრაუზერის გამოყენება"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"დარეკვა"</string>
@@ -2414,6 +2401,10 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"სამსახური 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"სატესტო"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"საერთო"</string>
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"სამსახურის პროფილი"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"კერძო სივრცე"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"კლონის შექმნა"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"საერთო"</string>
<string name="redacted_notification_message" msgid="1520587845842228816">"სენსიტიური შეტყობინების კონტენტი დამალულია"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"ეკრანის გაზიარებიდან აპის კონტენტი დამალულია უსაფრთხოების მიზნით"</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 6f02f52..116166d 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> секундтан кейін"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Басқа нөмірге бағытталмады"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: қайта бағытталған жоқ."</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Мобильдік желінің қауіпсіздігі"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Шифрлау, шифрланбаған желілер туралы хабарландырулар"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"Құрылғы идентификаторы алынды"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"<xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> SIM картасын қолдану кезінде маңайдағы желіде сағат <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> шамасында құрылғыңыздың бірегей идентификаторы (IMSI не IMEI) жазып алынды."</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"<xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> SIM картасын қолдану кезінде маңайдағы желіде сағат <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> шамасында құрылғыңыздың бірегей идентификаторы (IMSI не IMEI) жазып алынды.\n\nОрналасқан жеріңіз, әрекеттеріңіз не жеке басыңыз туралы ақпарат тіркелді. Мұндай жағдай жиі болып тұратынына қарамастан, ол өз құпиялығына үлкен мән беретін адамдарға қиындық келтіруі мүмкін."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Шифрланған желіге (<xliff:g id="NETWORK_NAME">%1$s</xliff:g>) қосылды"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"Енді <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM картасымен қосылу қорғалған."</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Шифрланбаған желіге қосылды"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM картасын пайдаланған кезде, қазіргі уақытта қоңырауларға, хабарларға және деректерге қауіп төнеді."</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM картасын пайдаланған кезде, қазіргі уақытта қоңырауларға, хабарларға және деректерге қауіп төнеді.\n\nБайланыс қайта шифрланғанда, тағы бір хабарландыру келеді."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Мобильдік желінің қауіпсіздік параметрлері"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Толық ақпарат"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"Түсінікті"</string>
<string name="fcComplete" msgid="1080909484660507044">"Функция коды толық."</string>
<string name="fcError" msgid="5325116502080221346">"Байланыс мәселесі немесе функция коды жарамсыз."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"Жарайды"</string>
@@ -371,8 +359,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Скриншот жасау"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Дисплейдің скриншотын жасай аласыз."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Алғы көрініс, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"жабу"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"күйін көрсету тақтасын өшіру немесе өзгерту"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Қолданбаға күй жолағын өшіруге немесе жүйелік белгішелерді қосуға және жоюға рұқсат береді."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"күй жолағы болу"</string>
@@ -1977,7 +1964,7 @@
<string name="maximize_button_text" msgid="4258922519914732645">"Жазу"</string>
<string name="close_button_text" msgid="10603510034455258">"Жабу"</string>
<string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
- <string name="call_notification_answer_action" msgid="5999246836247132937">"Жауап"</string>
+ <string name="call_notification_answer_action" msgid="5999246836247132937">"Жауап беру"</string>
<string name="call_notification_answer_video_action" msgid="2086030940195382249">"Бейне"</string>
<string name="call_notification_decline_action" msgid="3700345945214000726">"Қабылдамау"</string>
<string name="call_notification_hang_up_action" msgid="9130720590159188131">"Тұтқаны қою"</string>
@@ -2157,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Режим туралы хабарландыру"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Батареяны үнемдеу режимі қосулы"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Батарея шығынын азайтсаңыз, батареяның жұмысы ұзарады."</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"Батареяны үнемдеу режимі қосулы"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"Батарея жұмысының ұзақтығын арттыру үшін батареяны үнемдеу режимі қосылған."</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Батареяны үнемдеу режимі"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Батареяны үнемдеу режимі өшірілді"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Телефонның заряды жеткілікті. Функцияларға енді шектеу қойылмайды."</string>
@@ -2231,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Жұмыс қолданбасына ауысу керек пе?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Ұйымыңыз тек жұмыс қолданбаларынан қоңырау шалуға рұқсат етеді."</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Ұйымыңыз тек жұмыс қолданбаларынан хабар жіберуге рұқсат етеді."</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Жеке Телефон қолданбасынан ғана қоңырау шала аласыз. Бұл қолданба арқылы жасалған қоңыраулар жеке қоңыраулар тарихына қосылады."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"SMS хабарларын жеке Messages қолданбасынан ғана жібере аласыз."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Жеке браузерді пайдалану"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Жұмыс браузерін пайдалану"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Қоңырау шалу"</string>
@@ -2414,8 +2401,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Жұмыс 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Сынақ"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Жалпы"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Жұмыс профилі"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Құпия кеңістік"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Клон"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Жалпы"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Хабарландырудың құпия контенті жасырылған."</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Қауіпсіздік мақсатында қолданба контенті экранды көрсету кезінде жасырылды."</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Жерсерік қызметіне автоматты түрде қосылды"</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 55d7366..456256c 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> បន្ទាប់ពី <xliff:g id="TIME_DELAY">{2}</xliff:g> វិនាទី"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g> ៖ មិនបានបញ្ជូនបន្ត"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g> ៖ មិនបានបញ្ជូនបន្ត"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"សុវត្ថិភាពបណ្ដាញទូរសព្ទចល័ត"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"ការអ៊ីនគ្រីប ការជូនដំណឹងសម្រាប់បណ្ដាញដែលមិនបានអ៊ីនគ្រីប"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"បានចូលប្រើប្រាស់លេខសម្គាល់ឧបករណ៍"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"នៅម៉ោង <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> បណ្ដាញនៅជិតបានកត់ត្រាលេខសម្គាល់ពិសេស (IMSI ឬ IMEI) របស់ឧបករណ៍អ្នក ពេលកំពុងប្រើស៊ីម <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> របស់អ្នក"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"នៅម៉ោង <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> បណ្ដាញនៅជិតបានកត់ត្រាលេខសម្គាល់ពិសេស (IMSI ឬ IMEI) របស់ឧបករណ៍អ្នក ពេលកំពុងប្រើស៊ីម <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> របស់អ្នក។\n\nនេះមានន័យថា ទីតាំង សកម្មភាព ឬអត្តសញ្ញាណរបស់អ្នកត្រូវបានចុះកំណត់ហេតុ។ នេះគឺជាការអនុវត្តទូទៅ ប៉ុន្តែអាចនឹងមានបញ្ហាសម្រាប់អ្នកដែលមានកង្វល់ពាក់ព័ន្ធនឹងឯកជនភាព។"</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"បានភ្ជាប់ទៅបណ្ដាញដែលបានអ៊ីនគ្រីប <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"ការតភ្ជាប់ស៊ីម <xliff:g id="NETWORK_NAME">%1$s</xliff:g> កាន់តែមានសុវត្ថិភាពឥឡូវនេះ"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"បានភ្ជាប់ទៅបណ្ដាញដែលមិនបានអ៊ីនគ្រីប"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"បច្ចុប្បន្ន ការហៅទូរសព្ទ សារ និងទិន្នន័យកាន់តែងាយរងគ្រោះ ពេលកំពុងប្រើស៊ីម <xliff:g id="NETWORK_NAME">%1$s</xliff:g> របស់អ្នក"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"បច្ចុប្បន្ន ការហៅទូរសព្ទ សារ និងទិន្នន័យកាន់តែងាយរងគ្រោះ ពេលកំពុងប្រើស៊ីម <xliff:g id="NETWORK_NAME">%1$s</xliff:g> របស់អ្នក។\n\nនៅពេលការតភ្ជាប់របស់អ្នកត្រូវបានអ៊ីនគ្រីបម្ដងទៀត អ្នកនឹងទទួលបានការជូនដំណឹងផ្សេងទៀត។"</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"ការកំណត់សុវត្ថិភាពបណ្ដាញទូរសព្ទចល័ត"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"ស្វែងយល់បន្ថែម"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"យល់ហើយ"</string>
<string name="fcComplete" msgid="1080909484660507044">"កូដលក្ខណៈពេញលេញ។"</string>
<string name="fcError" msgid="5325116502080221346">"បញ្ហាការតភ្ជាប់ ឬកូដលក្ខណៈមិនត្រឹមត្រូវ។"</string>
<string name="httpErrorOk" msgid="6206751415788256357">"យល់ព្រម"</string>
@@ -2156,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"ការជូនដំណឹងព័ត៌មានរបស់មុខងារទម្លាប់"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"បានបើកមុខងារសន្សំថ្ម"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"ការកាត់បន្ថយការប្រើប្រាស់ថ្ម ដើម្បីបង្កើនកម្រិតថាមពលថ្ម"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"មុខងារសន្សំថ្មត្រូវបានបើក"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"មុខងារសន្សំថ្មត្រូវបានបើក ដើម្បីបង្កើនកម្រិតថាមពលថ្ម"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"មុខងារសន្សំថ្ម"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"មុខងារសន្សំថ្មត្រូវបានបិទ"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"ទូរសព្ទមានកម្រិតថ្មគ្រប់គ្រាន់។ មុខងារផ្សេងៗមិនត្រូវបានរឹតបន្តឹងទៀតទេ។"</string>
@@ -2230,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"ប្ដូរទៅកម្មវិធីការងារឬ?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"ស្ថាប័នរបស់អ្នកអនុញ្ញាតឱ្យអ្នកធ្វើការហៅទូរសព្ទពីកម្មវិធីការងារតែប៉ុណ្ណោះ"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"ស្ថាប័នរបស់អ្នកអនុញ្ញាតឱ្យអ្នកផ្ញើសារពីកម្មវិធីការងារតែប៉ុណ្ណោះ"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"អ្នកអាចធ្វើការហៅទូរសព្ទពីកម្មវិធីទូរសព្ទផ្ទាល់ខ្លួនរបស់អ្នកតែប៉ុណ្ណោះ។ ការហៅទូរសព្ទដែលបានធ្វើឡើងដោយប្រើទូរសព្ទផ្ទាល់ខ្លួននឹងត្រូវបានបញ្ចូលទៅប្រវត្តិហៅទូរសព្ទផ្ទាល់ខ្លួនរបស់អ្នក។"</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"អ្នកអាចផ្ញើសារ SMS ពីកម្មវិធី Messages ផ្ទាល់ខ្លួនរបស់អ្នកតែប៉ុណ្ណោះ។"</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"ប្រើកម្មវិធីរុករកតាមអ៊ីនធឺណិតផ្ទាល់ខ្លួន"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"ប្រើកម្មវិធីរុករកតាមអ៊ីនធឺណិតសម្រាប់ការងារ"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"ហៅទូរសព្ទ"</string>
@@ -2413,6 +2401,10 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"ការងារទី 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"ការធ្វើតេស្ត"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"ទូទៅ"</string>
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"កម្រងព័ត៌មានការងារ"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"លំហឯកជន"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"ក្លូន"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"ទូទៅ"</string>
<string name="redacted_notification_message" msgid="1520587845842228816">"បានលាក់ខ្លឹមសារជូនដំណឹងដែលមានលក្ខណៈរសើប"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"បានលាក់ខ្លឹមសារកម្មវិធីពីការបង្ហាញអេក្រង់ដើម្បីសុវត្ថិភាព"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 1ffcf10..97f0136 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="TIME_DELAY">{2}</xliff:g> ಸೆಕೆಂಡುಗಳ ನಂತರ <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ಫಾರ್ವರ್ಡ್ ಮಾಡಲಾಗಿಲ್ಲ"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ಫಾರ್ವರ್ಡ್ ಮಾಡಲಾಗಿಲ್ಲ"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"ಮೊಬೈಲ್ ನೆಟ್ವರ್ಕ್ ಸೆಕ್ಯೂರಿಟಿ"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"ಎನ್ಕ್ರಿಪ್ಶನ್, ಎನ್ಕ್ರಿಪ್ಟ್ ಮಾಡದ ನೆಟ್ವರ್ಕ್ಗಳಿಗೆ ನೋಟಿಫಿಕೇಶನ್ಗಳು"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"ಸಾಧನದ ID ಅನ್ನು ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಲಾಗಿದೆ"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"<xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> ಸಮಯದಲ್ಲಿ, ನಿಮ್ಮ ಸಾಧನದ ಅನನ್ಯ ID (IMSI ಅಥವಾ IMEI) ಅನ್ನು ನಿಮ್ಮ <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> SIM ಕಾರ್ಡ್ ಬಳಸುವಾಗ ಹತ್ತಿರದ ನೆಟ್ವರ್ಕ್ನಿಂದ ರೆಕಾರ್ಡ್ ಮಾಡಲಾಗಿದೆ"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"<xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> ಸಮಯದಲ್ಲಿ, ನಿಮ್ಮ ಸಾಧನದ ಅನನ್ಯ ID (IMSI ಅಥವಾ IMEI) ಅನ್ನು ನಿಮ್ಮ <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> SIM ಕಾರ್ಡ್ ಬಳಸುವಾಗ ಹತ್ತಿರದ ನೆಟ್ವರ್ಕ್ನಿಂದ ರೆಕಾರ್ಡ್ ಮಾಡಲಾಗಿದೆ.\n\nಇದರರ್ಥ ನಿಮ್ಮ ಸ್ಥಳ, ಚಟುವಟಿಕೆ ಅಥವಾ ಗುರುತನ್ನು ಲಾಗ್ ಮಾಡಲಾಗಿದೆ. ಇದು ಸಾಮಾನ್ಯ ವಿಧಾನವಾಗಿದೆ ಆದರೆ ಗೌಪ್ಯತೆಯ ಕುರಿತು ಕಾಳಜಿವಹಿಸುವವರಿಗೆ ಸಮಸ್ಯೆಯಾಗಬಹುದು."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"ಎನ್ಕ್ರಿಪ್ಟ್ ಮಾಡಿದ <xliff:g id="NETWORK_NAME">%1$s</xliff:g> ನೆಟ್ವರ್ಕ್ಗೆ ಕನೆಕ್ಟ್ ಮಾಡಲಾಗಿದೆ"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM ಕನೆಕ್ಷನ್ ಈಗ ಹೆಚ್ಚು ಸುರಕ್ಷಿತವಾಗಿದೆ"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"ಎನ್ಕ್ರಿಪ್ಟ್ ಮಾಡದ ನೆಟ್ವರ್ಕ್ಗೆ ಕನೆಕ್ಟ್ ಮಾಡಲಾಗಿದೆ"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"ನಿಮ್ಮ <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM ಕಾರ್ಡ್ ಬಳಸುವಾಗ ಕರೆಗಳು, ಸಂದೇಶಗಳು ಮತ್ತು ಡೇಟಾ ಪ್ರಸ್ತುತ ಹೆಚ್ಚು ಸೂಕ್ಷ್ಮವಾಗಿರುತ್ತದೆ."</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"ನಿಮ್ಮ <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM ಕಾರ್ಡ್ ಬಳಸುವಾಗ ಕರೆಗಳು, ಸಂದೇಶಗಳು ಮತ್ತು ಡೇಟಾ ಪ್ರಸ್ತುತ ಹೆಚ್ಚು ಸೂಕ್ಷ್ಮವಾಗಿರುತ್ತದೆ.\n\nನಿಮ್ಮ ಕನೆಕ್ಷನ್ ಅನ್ನು ಮತ್ತೆ ಎನ್ಕ್ರಿಪ್ಟ್ ಮಾಡಿದಾಗ, ನೀವು ಇನ್ನೊಂದು ನೋಟಿಫಿಕೇಶನ್ ಅನ್ನು ಪಡೆಯುತ್ತೀರಿ."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"ಮೊಬೈಲ್ ನೆಟ್ವರ್ಕ್ ಸೆಕ್ಯೂರಿಟಿ ಸೆಟ್ಟಿಂಗ್ಗಳು"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"ಇನ್ನಷ್ಟು ತಿಳಿಯಿರಿ"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"ಅರ್ಥವಾಯಿತು"</string>
<string name="fcComplete" msgid="1080909484660507044">"ವೈಶಿಷ್ಟ್ಯದ ಕೋಡ್ ಪೂರ್ಣಗೊಂಡಿದೆ."</string>
<string name="fcError" msgid="5325116502080221346">"ಸಂಪರ್ಕದ ಸಮಸ್ಯೆ ಅಥವಾ ಅಮಾನ್ಯ ವೈಶಿಷ್ಟ್ಯದ ಕೋಡ್."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"ಸರಿ"</string>
@@ -2156,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"ದೈನಂದಿನ ಸ್ಥಿತಿಯ ಮಾಹಿತಿಯ ನೋಟಿಫಿಕೇಶನ್"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"ಬ್ಯಾಟರಿ ಸೇವರ್ ಅನ್ನು ಆನ್ ಮಾಡಲಾಗಿದೆ"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"ಬ್ಯಾಟರಿ ಬಾಳಿಕೆಯನ್ನು ವಿಸ್ತರಿಸಲು ಬ್ಯಾಟರಿ ಬಳಕೆಯನ್ನು ಕಡಿಮೆ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"ಬ್ಯಾಟರಿ ಸೇವರ್ ಆನ್ ಆಗಿದೆ"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"ಬ್ಯಾಟರಿ ಬಾಳಿಕೆಯನ್ನು ವಿಸ್ತರಿಸಲು ಬ್ಯಾಟರಿ ಸೇವರ್ ಅನ್ನು ಆನ್ ಮಾಡಲಾಗಿದೆ"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"ಬ್ಯಾಟರಿ ಸೇವರ್"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"ಬ್ಯಾಟರಿ ಸೇವರ್ ಅನ್ನು ಆಫ್ ಮಾಡಲಾಗಿದೆ"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"ಫೋನ್ನಲ್ಲಿ ಸಾಕಷ್ಟು ಚಾರ್ಜ್ ಇದೆ. ಇನ್ನು ಮುಂದೆ ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ನಿರ್ಬಂಧಿಸಲಾಗುವುದಿಲ್ಲ."</string>
@@ -2230,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"ಕೆಲಸಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಆ್ಯಪ್ಗೆ ಬದಲಿಸಬೇಕೇ?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"ನಿಮ್ಮ ಸಂಸ್ಥೆಯು ಕೆಲಸಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಆ್ಯಪ್ಗಳಿಂದ ಮಾತ್ರ ಕರೆಗಳನ್ನು ಮಾಡಲು ನಿಮಗೆ ಅನುಮತಿಸುತ್ತದೆ"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"ನಿಮ್ಮ ಸಂಸ್ಥೆಯು ಕೆಲಸಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಆ್ಯಪ್ಗಳಿಂದ ಮಾತ್ರ ಸಂದೇಶಗಳನ್ನು ಕಳುಹಿಸಲು ನಿಮಗೆ ಅನುಮತಿಸುತ್ತದೆ"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"ನಿಮ್ಮ ವೈಯಕ್ತಿಕ ಫೋನ್ ಆ್ಯಪ್ನಿಂದ ಮಾತ್ರ ನೀವು ಫೋನ್ ಕರೆಗಳನ್ನು ಮಾಡಬಹುದು. ವೈಯಕ್ತಿಕ ಫೋನ್ಗಳಿಂದ ಮಾಡಿದ ಕರೆಗಳನ್ನು ನಿಮ್ಮ ವೈಯಕ್ತಿಕ ಕರೆ ಇತಿಹಾಸಕ್ಕೆ ಸೇರಿಸಲಾಗುತ್ತದೆ."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"ನಿಮ್ಮ ವೈಯಕ್ತಿಕ Messages ಆ್ಯಪ್ನಿಂದ ಮಾತ್ರ ನೀವು SMS ಸಂದೇಶಗಳನ್ನು ಕಳುಹಿಸಬಹುದು."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"ವೈಯಕ್ತಿಕ ಬ್ರೌಸರ್ ಬಳಸಿ"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"ಉದ್ಯೋಗ ಬ್ರೌಸರ್ ಬಳಸಿ"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"ಕರೆ ಮಾಡಿ"</string>
@@ -2413,6 +2401,10 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"ಕೆಲಸ 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"ಪರೀಕ್ಷೆ"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"ಸಮುದಾಯ"</string>
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"ಪ್ರೈವೆಟ್ ಸ್ಪೇಸ್"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"ಕ್ಲೋನ್"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"ಸಮುದಾಯ"</string>
<string name="redacted_notification_message" msgid="1520587845842228816">"ಸೂಕ್ಷ್ಮ ನೋಟಿಫಿಕೇಶನ್ ಕಂಟೆಂಟ್ ಅನ್ನು ಮರೆಮಾಡಲಾಗಿದೆ"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"ಭದ್ರತೆಗಾಗಿ ಸ್ಕ್ರೀನ್ ಹಂಚಿಕೊಳ್ಳುವಿಕೆಯಲ್ಲಿ ಆ್ಯಪ್ ಕಂಟೆಂಟ್ ಅನ್ನು ಮರೆಮಾಡಲಾಗಿದೆ"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index a6cfe2a..df29128 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g><xliff:g id="TIME_DELAY">{2}</xliff:g>초 후"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: 착신전환 안됨"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: 착신전환 안됨"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"모바일 네트워크 보안"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"암호화, 암호화되지 않은 네트워크에 대한 알림"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"기기 ID 액세스됨"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"<xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>에 <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> SIM을 사용하는 동안 근처 네트워크에서 기기의 고유 ID(IMSI 또는 IMEI)를 기록했습니다."</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"<xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>에 <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> SIM을 사용하는 동안 근처 네트워크에서 기기의 고유 ID(IMSI 또는 IMEI)를 기록했습니다.\n\n즉, 사용자의 위치, 활동 또는 ID가 기록되었습니다. 이는 일반적인 관행이지만 개인 정보 보호에 대해 우려하는 사용자에게는 문제가 될 수도 있습니다."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"암호화된 네트워크 <xliff:g id="NETWORK_NAME">%1$s</xliff:g>에 연결됨"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"이제 <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM 연결의 보안이 강화되었습니다."</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"암호화되지 않은 네트워크에 연결됨"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"현재 <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM을 사용하는 동안 통화, 메시지, 데이터의 보안이 취약합니다."</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"현재 <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM을 사용하는 동안 통화, 메시지, 데이터의 보안이 취약합니다.\n\n연결이 다시 암호화되면 또 다른 알림을 받게 됩니다"</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"모바일 네트워크 보안 설정"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"자세히 알아보기"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"확인"</string>
<string name="fcComplete" msgid="1080909484660507044">"기능 코드가 완료되었습니다."</string>
<string name="fcError" msgid="5325116502080221346">"연결에 문제가 있거나 기능 코드가 잘못되었습니다."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"확인"</string>
@@ -371,8 +359,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"스크린샷 촬영"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"디스플레이 스크린샷을 촬영할 수 있습니다."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"미리보기, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"닫기"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"상태 표시줄 사용 중지 또는 수정"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"앱이 상태 표시줄을 사용중지하거나 시스템 아이콘을 추가 및 제거할 수 있도록 허용합니다."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"상태 표시줄에 위치"</string>
@@ -2157,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"루틴 모드 정보 알림"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"절전 모드 사용 설정됨"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"배터리 사용량을 줄여서 배터리 수명을 늘립니다."</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"절전 모드 사용 중"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"배터리 수명을 늘리기 위해 절전 모드가 사용 설정되었습니다"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"절전 모드"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"절전 모드가 사용 중지되었습니다"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"휴대전화의 배터리가 충분하므로 기능이 더 이상 제한되지 않습니다"</string>
@@ -2231,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"직장 앱으로 전환할까요?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"귀하의 조직에서 직장 앱을 사용한 통화만 허용합니다."</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"귀하의 조직에서 직장 앱을 사용한 메시지 전송만 허용합니다."</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"개인 전화 앱에서만 전화를 걸 수 있습니다. 개인 전화로 통화한 내역은 개인 통화 기록에 추가됩니다."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"개인 메시지 앱에서만 SMS 메시지를 보낼 수 있습니다."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"개인 브라우저 사용"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"직장 브라우저 사용"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"통화"</string>
@@ -2414,8 +2401,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"직장 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"테스트"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"공동"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"직장 프로필"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"비공개 스페이스"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"클론"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"공동"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"민감한 알림 콘텐츠 숨김"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"보안을 위해 화면 공유에서 앱 콘텐츠가 숨겨집니다."</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"위성에 자동 연결됨"</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index e21a76c..9511db4f 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> секунддан кийин"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Багытталган эмес"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Багытталган эмес"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Мобилдик тармактын коопсуздугу"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Шифрлөө, шифрленбеген тармактар жөнүндө билдирмелер"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"Түзмөктүн идентификатору колдонулду"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"<xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> SIM картасын колдонуп жатканда жакын жердеги тармакта түзмөгүңүздүн өзгөчө идентификатору (IMSI же IMEI) жазылды"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"<xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> SIM картасын колдонуп жатканда жакын жердеги тармакта түзмөгүңүздүн өзгөчө идентификатору (IMSI же IMEI) жазылды.\n\nЖүргөн жериңиз, аракеттериңиз же өздүгүңүз тууралуу маалымат катталды. Бул адаттагы көрүнүш болсо да, купуялыгы жөнүндө тынчсызданган адамдарга маселе жаратышы мүмкүн."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Шифрленген тармакка (<xliff:g id="NETWORK_NAME">%1$s</xliff:g>) туташты"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"Эми <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM картасы менен туташуу коопсуз болуп калды"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Шифрленбеген тармакка туташты"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Учурда <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM картасын колдонсоңуз, чалууларга, билдирүүлөргө жана маалыматтарга коркунуч жаралышы мүмкүн"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Учурда <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM картасын колдонсоңуз, чалууларга, билдирүүлөргө жана маалыматтарга коркунуч жаралышы мүмкүн.\n\nТуташууңуз кайра шифрленгенде дагы бир билдирме аласыз."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Мобилдик тармактын коопсуздук параметрлери"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Кеңири маалымат"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"Түшүндүм"</string>
<string name="fcComplete" msgid="1080909484660507044">"Функция коду аткарылды."</string>
<string name="fcError" msgid="5325116502080221346">"Туташууда көйгөй чыкты же функция коду жараксыз."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"Жарайт"</string>
@@ -371,8 +359,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Скриншот тартып алуу"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Дисплейдин скриншотун тартып алсаңыз болот."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Алдын ала көрүү, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"жабуу"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"абал тилкесин өчүрүү же өзгөртүү"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Колдонмого абал тилкесин өчүрүү же тутум сүрөтчөлөрүн кошуу же алып салуу мүмкүнчүлүгүн берет."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"абал тилкесинин милдетин аткаруу"</string>
@@ -1981,7 +1968,7 @@
<string name="call_notification_answer_video_action" msgid="2086030940195382249">"Видео"</string>
<string name="call_notification_decline_action" msgid="3700345945214000726">"Четке кагуу"</string>
<string name="call_notification_hang_up_action" msgid="9130720590159188131">"Чалууну бүтүрүү"</string>
- <string name="call_notification_incoming_text" msgid="6143109825406638201">"Кирүүчү чалуу"</string>
+ <string name="call_notification_incoming_text" msgid="6143109825406638201">"Чалып жатат"</string>
<string name="call_notification_ongoing_text" msgid="3880832933933020875">"Учурдагы чалуу"</string>
<string name="call_notification_screening_text" msgid="8396931408268940208">"Кирүүчү чалууну иргөө"</string>
<string name="default_notification_channel_label" msgid="3697928973567217330">"Категорияларга бөлүнгөн эмес"</string>
@@ -2157,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Режимдин адаттагы билдирмеси"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Батареяны үнөмдөгүч күйгүзүлдү"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Кубат үнөмдөлсө, батарея көбүрөөк убакытка жетет"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"Батареяны үнөмдөгүч режими күйүк"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"Батареянын кубатынын мөөнөтүн узартуу үчүн Батареяны үнөмдөгүч режими күйгүзүлдү"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Батареяны үнөмдөгүч"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Батареяны үнөмдөө режими өчүк"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Телефондун кубаты жетиштүү. Функциялар мындан ары чектелбейт."</string>
@@ -2231,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Жумуш колдонмосуна которуласызбы?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Уюмуңуз жумуш колдонмолорунан гана чалууга уруксат берет"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Уюмуңуз билдирүүлөрдү жумуш колдонмолорунан гана жөнөтүүгө уруксат берет"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Жеке \"Телефон\" колдонмосунан гана чала аласыз. Жеке \"Телефон\" колдонмосунан аткарылган чалуулар жеке чалуулар таржымалына кошулат."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"SMS билдирүүлөрдү жеке Жазышуулар колдонмосунан гана жөнөтө аласыз."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Жеке серепчини колдонуу"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Жумуш серепчисин колдонуу"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Чалуу"</string>
@@ -2414,8 +2401,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Жумуш 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Сыноо"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Жалпы"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Жумуш профили"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Жеке мейкиндик"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Клон"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Жалпы"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Купуя билдирменин мазмуну жашырылган"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Коопсуздук үчүн колдонмодогу контент бөлүшүлгөн экрандан жашырылды"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Спутникке автоматтык түрдө туташтырылган"</string>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index 4624d5e..a0aded4 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -2144,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"ການແຈ້ງເຕືອນຂໍ້ມູນໂໝດກິດຈະວັດປະຈຳວັນ"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"ເປີດໃຊ້ຕົວປະຢັດແບັດເຕີຣີແລ້ວ"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"ກຳລັງຫຼຸດການໃຊ້ແບັດເຕີຣີເພື່ອຍືດອາຍຸແບັດເຕີຣີ"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"ຕົວປະຢັດແບັດເຕີຣີເປີດຢູ່"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"ຕົວປະຢັດແບັດເຕີຣີເປີດຢູ່ເພື່ອຍືດອາຍຸແບັດເຕີຣີ"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"ຕົວປະຢັດແບັດເຕີຣີ"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"ປິດຕົວປະຢັດແບັດເຕີຣີແລ້ວ"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"ໂທລະສັບມີໄຟພຽງພໍແລ້ວ. ບໍ່ມີການຈຳກັດຄຸນສົມບັດອີກຕໍ່ໄປແລ້ວ."</string>
@@ -2399,6 +2401,10 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"ວຽກ 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"ທົດສອບ"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"ສ່ວນກາງ"</string>
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"ໂປຣໄຟລ໌ບ່ອນເຮັດວຽກ"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"ພື້ນທີ່ສ່ວນບຸກຄົນ"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"ໂຄລນ"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"ສ່ວນກາງ"</string>
<string name="redacted_notification_message" msgid="1520587845842228816">"ເນື້ອຫາການແຈ້ງເຕືອນທີ່ລະອຽດອ່ອນເຊື່ອງຢູ່"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"ເນື້ອຫາແອັບຖືກເຊື່ອງໄວ້ຈາກການແບ່ງປັນໜ້າຈໍເພື່ອຄວາມປອດໄພ"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 31ede33..837bff7 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -155,31 +155,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> po <xliff:g id="TIME_DELAY">{2}</xliff:g> sek."</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: neperadresuota"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: neperadresuota"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Mobiliojo ryšio tinklo apsauga"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Šifruotė, nešifruotų tinklų pranešimai"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"Pasiektas įrenginio ID"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"<xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> netoliese esantis tinklas įrašė jūsų įrenginio unikalų ID (IMSI arba IMEI), kol buvo naudojama jūsų „<xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>“ SIM kortelė."</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"<xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> netoliese esantis tinklas įrašė jūsų įrenginio unikalų ID (IMSI arba IMEI), kol buvo naudojama jūsų „<xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>“ SIM kortelė.\n\nTai reiškia, kad jūsų vietovė, veikla ar tapatybė buvo užregistruoti. Tai įprasta praktika, bet žmonėms, kurie nerimauja dėl privatumo, gali kilti problemų."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Prisijungta prie šifruoto tinklo „<xliff:g id="NETWORK_NAME">%1$s</xliff:g>“"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"„<xliff:g id="NETWORK_NAME">%1$s</xliff:g>“ SIM kortelės ryšys dabar saugesnis"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Prisijungta prie nešifruoto tinklo"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Skambučiai, pranešimai ir duomenys dabar gerokai pažeidžiamesni, kol naudojama „<xliff:g id="NETWORK_NAME">%1$s</xliff:g>“ SIM kortelė."</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Skambučiai, pranešimai ir duomenys dabar gerokai pažeidžiamesni, kol naudojama „<xliff:g id="NETWORK_NAME">%1$s</xliff:g>“ SIM kortelė.\n\nKai ryšys vėl bus užšifruotas, gausite kitą pranešimą."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Mobiliojo ryšio tinklo saugos nustatymai"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Sužinokite daugiau"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"Supratau"</string>
<string name="fcComplete" msgid="1080909484660507044">"Funkcijos kodas baigtas."</string>
<string name="fcError" msgid="5325116502080221346">"Ryšio problema arba neteisingas funkcijos kodas."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"Gerai"</string>
@@ -2158,6 +2146,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Veiksmų sekos režimo informacijos pranešimas"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Įjungta akumuliatoriaus tausojimo priemonė"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Sumažinamas akumuliatoriaus energijos vartojimas, kad akumuliatorius veiktų ilgiau"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"Akumuliatoriaus tausojimo priemonė įjungta"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"Akumuliatoriaus tausojimo priemonė įjungta, kad akumuliatorius veiktų ilgiau"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Akumuliatoriaus tausojimo priemonė"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Akumuliatoriaus tausojimo priemonė išjungta"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Telefonas pakankamai įkrautas. Funkcijos neberibojamos."</string>
@@ -2232,10 +2222,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Perjungti į darbo programą?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Jūsų organizacija leidžia skambinti tik iš darbo programų"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Jūsų organizacija leidžia siųsti pranešimus tik iš darbo programų"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Galite skambinti telefonu tik iš asmeninės Telefono programos. Naudojant asmeninę Telefono programą atlikti skambučiai bus pridėti prie jūsų asmeninės skambučių istorijos."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"Galite siųsti SMS pranešimus tik iš asmeninės programos „Messages“."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Naudoti asmeninę naršyklę"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Naudoti darbo naršyklę"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Skambinti"</string>
@@ -2415,6 +2403,10 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Darbas (3)"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Bandymas"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Bendruomenės"</string>
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Darbo profilis"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Privati erdvė"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Klonuoti"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Bendruomenės"</string>
<string name="redacted_notification_message" msgid="1520587845842228816">"Neskelbtinos informacijos pranešimo turinys paslėptas"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Programos turinys paslėptas bendrinant ekraną saugumo sumetimais"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 93d6a4f..4e24473 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -154,31 +154,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> pēc <xliff:g id="TIME_DELAY">{2}</xliff:g> sekundes(-ēm)"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: nav pāradresēts"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: nav pāradresēts"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Mobilā tīkla drošība"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Šifrēšana un paziņojumi par nešifrētiem tīkliem"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"Piekļūts ierīces ID"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"Pulksten <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> tuvējā tīklā tika reģistrēts jūsu ierīces unikālais ID (IMSI vai IMEI), kamēr izmantojāt savu <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> SIM karti."</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"Pulksten <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> tuvējā tīklā tika reģistrēts jūsu ierīces unikālais ID (IMSI vai IMEI), kamēr izmantojāt savu <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> SIM karti.\n\nTas nozīmē, ka tika reģistrēta jūsu atrašanās vieta, darbības vai identitāte. Šāda prakse ir ierasta, tomēr var radīt problēmas personām, kurām ir bažas par konfidencialitāti."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Izveidots savienojums ar šifrēto tīklu <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"Tagad <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM savienojums ir drošāks."</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Izveidots savienojums ar nešifrētu tīklu"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Pašlaik, kamēr izmantojat <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM karti, zvani, ziņojumi un dati ir mazāk aizsargāti."</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Pašlaik, kamēr izmantojat <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM karti, zvani, ziņojumi un dati ir mazāk aizsargāti.\n\nKad savienojums atkal būs šifrēts, saņemsiet jaunu paziņojumu."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Mobilā tīkla drošības iestatījumi"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Uzzināt vairāk"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"Labi"</string>
<string name="fcComplete" msgid="1080909484660507044">"Funkcijas kods ir pabeigts."</string>
<string name="fcError" msgid="5325116502080221346">"Savienojuma problēma vai nederīgs funkcijas kods."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"Labi"</string>
@@ -372,8 +360,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ekrānuzņēmuma izveide"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Var izveidot displeja ekrānuzņēmumu."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"<xliff:g id="DREAM_NAME">%1$s</xliff:g> (priekšskatījums)"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"nerādīt"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"atspējot vai pārveidot statusa joslu"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Ļauj lietotnei atspējot statusa joslu vai pievienot un noņemt sistēmas ikonas."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"Būt par statusa joslu"</string>
@@ -2158,6 +2145,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Informatīvs paziņojums par akumulatoru"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Ieslēgts akumulatora enerģijas taupīšanas režīms"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Tiek samazināts akumulatora lietojums, lai paildzinātu akumulatora darbību."</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"Akumulatora enerģijas taupīšanas režīms ir ieslēgts"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"Akumulatora enerģijas taupīšanas režīms ir ieslēgts, lai paildzinātu akumulatora darbību."</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Akumulatora enerģijas taupīšanas režīms"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Akumulatora enerģijas taupīšanas režīms ir izslēgts"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Tālruņa uzlādes līmenis ir pietiekams. Funkcijas vairs netiek ierobežotas."</string>
@@ -2232,10 +2221,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Vai pārslēgties uz darba lietotni?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Jūsu organizācija ļauj jums veikt zvanus tikai no darba lietotnēm."</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Jūsu organizācija ļauj jums sūtīt ziņojumus tikai no darba lietotnēm."</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Tālruņa zvanus varat veikt tikai no personīgās lietotnes Tālrunis. Zvani, kam izmantosiet personīgo lietotni Tālrunis, tiks pievienoti jūsu personīgajai zvanu vēsturei."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"Īsziņas varat sūtīt tikai no personīgās lietotnes Ziņojumi."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Izmantot personīgo pārlūku"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Izmantot darba pārlūku"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Zvanīt"</string>
@@ -2415,8 +2402,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Darbam (3.)"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Testēšanai"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Kopīgs"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Darba profils"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Privātā telpa"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Klons"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Kopīgs"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Sensitīvs paziņojuma saturs ir paslēpts"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Drošības nolūkos lietotnes saturs kopīgotajā ekrānā ir paslēpts"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Automātiski izveidots savienojums ar satelītu"</string>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 0166b67..3790be0 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> по <xliff:g id="TIME_DELAY">{2}</xliff:g> секунди"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: не е препратено"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: не е проследен"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Обезбедување на мобилна мрежа"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Шифрирање, известувања за нешифрирани мрежи"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"Пристапено е до ID на уредот"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"Во <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, мрежа во близина го сними уникатниот ID (IMSI или IMEI) на вашиот телефон со користење на вашата SIM-картичка на <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"Во <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, мрежа во близина го сними уникатниот ID (IMSI или IMEI) на вашиот телефон со користење на вашата SIM-картичка на <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>.\n\nОва значи дека вашата локација, активност или идентитет се евидентирани. Ова е вообичаена практика, но може да биде проблем за луѓето кои се загрижени за приватноста."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Поврзано со шифрирана мрежа <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"Врската со SIM-картичката на <xliff:g id="NETWORK_NAME">%1$s</xliff:g> сега е побезбедна"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Поврзано со нешифрирана мрежа"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Повиците, пораките и податоците во моментов се почувствителни додека ја користите вашата SIM-картичка на <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Повиците, пораките и податоците во моментов се почувствителни додека ја користите вашата SIM-картичка на <xliff:g id="NETWORK_NAME">%1$s</xliff:g>.\n\nКога вашата врска ќе биде шифрирана повторно, ќе добиете уште едно известување."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Поставки за обезбедување на мобилна мрежа"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Дознајте повеќе"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"Сфатив"</string>
<string name="fcComplete" msgid="1080909484660507044">"Кодот за карактеристиката заврши."</string>
<string name="fcError" msgid="5325116502080221346">"Проблем со поврзувањето или неважечки код за карактеристиката."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"Во ред"</string>
@@ -371,8 +359,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Зачувување слика од екранот"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Може да зачува слика од екранот."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Преглед, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"отфрли"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"оневозможи или измени статусна лента"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Дозволува апликацијата да ја оневозможи статусната лента или да додава или отстранува системски икони."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"да стане статусна лента"</string>
@@ -2157,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Известување за информации за режимот за рутини"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"„Штедачот на батерија“ е вклучен"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Се намалува користењето на батеријата за нејзино подолго траење"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"„Штедачот на батерија“ е вклучен"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"„Штедачот на батерија“ е вклучен за да се продолжи траењето на батеријата"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Штедач на батерија"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Штедачот на батерија е исклучен"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Телефонот е доволно полн. Функциите веќе не се ограничени."</string>
@@ -2231,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Да се префрли на работна апликација?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Вашата организација ви дозволува да упатувате повици само од работни апликации"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Вашата организација ви дозволува да испраќате пораки само од работни апликации"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Може да упатувате телефонски повици само од вашата лична апликација „Телефон“. Повиците упатени со личен телефон ќе се додадат во вашата лична историја на повици."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"Може да испраќате SMS-пораки само од вашата лична апликација Messages."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Користи личен прелистувач"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Користи работен прелистувач"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Повикај"</string>
@@ -2414,8 +2401,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Работен профил 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Профил за тестирање"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Профил на заедницата"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Работен профил"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Приватен простор"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Клониран профил"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Профил на заедницата"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Содржината на чувствителните известувања е скриена"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Од безбедносни причини, содржините на апликацијата се скриени од споделувањето екран"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Поврзано со сателит автоматски"</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index f90eddc..563efdb 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="TIME_DELAY">{2}</xliff:g> നിമിഷത്തിനുശേഷം <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: കൈമാറിയില്ല"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: കൈമാറിയിട്ടില്ല"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"മൊബൈൽ നെറ്റ്വർക്ക് സുരക്ഷ"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"എൻക്രിപ്ഷൻ, എൻക്രിപ്റ്റ് ചെയ്യാത്ത നെറ്റ്വര്ക്കുകൾക്കുള്ള അറിയിപ്പുകൾ"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"ഉപകരണ ഐഡി ആക്സസ് ചെയ്തു"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"നിങ്ങളുടെ <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> സിം ഉപയോഗിക്കുമ്പോൾ സമീപത്തുള്ള ഒരു നെറ്റ്വർക്ക് നിങ്ങളുടെ ഉപകരണത്തിൻ്റെ തനത് ഐഡി (IMSI അല്ലെങ്കിൽ IMEI), <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>-ന് റെക്കോർഡ് ചെയ്തു"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"നിങ്ങളുടെ <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> സിം ഉപയോഗിക്കുമ്പോൾ സമീപത്തുള്ള ഒരു നെറ്റ്വർക്ക് നിങ്ങളുടെ ഉപകരണത്തിൻ്റെ തനത് ഐഡി (IMSI അല്ലെങ്കിൽ IMEI), <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>-ന് റെക്കോർഡ് ചെയ്തു. \n\nനിങ്ങളുടെ ലൊക്കേഷൻ, ആക്റ്റിവിറ്റി അല്ലെങ്കിൽ ഐഡന്റിറ്റി ലോഗ് ചെയ്തിട്ടുണ്ടെന്നാണ് ഇതിനർത്ഥം. ഇത് പൊതുവായ രീതിയാണ്, എന്നാൽ സ്വകാര്യതയെ കുറിച്ച് ആശങ്കയുള്ളവർക്ക് ഇത് ഒരു പ്രശ്നമായിരിക്കാം."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> എന്ന എന്ക്രിപ്റ്റ് ചെയ്ത നെറ്റ്വര്ക്കിലേക്ക് കണക്റ്റ് ചെയ്തു"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> സിം കണക്ഷന് ഇപ്പോൾ കൂടുതൽ സുരക്ഷിതമാണ്"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"എൻക്രിപ്റ്റ് ചെയ്യാത്ത നെറ്റ്വര്ക്കിലേക്ക് കണക്റ്റ് ചെയ്തു"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> സിം ഉപയോഗിക്കുമ്പോൾ കോളുകൾ, സന്ദേശങ്ങൾ, ഡാറ്റ എന്നിവയുടെ സുരക്ഷ അപകടത്തിലാകാനുള്ള സാധ്യത വളരെ കൂടുതലാണ്"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> സിം ഉപയോഗിക്കുമ്പോൾ കോളുകൾ, സന്ദേശങ്ങൾ, ഡാറ്റ എന്നിവയുടെ സുരക്ഷ അപകടത്തിലാകാനുള്ള സാധ്യത വളരെ കൂടുതലാണ്.\n\nനിങ്ങളുടെ കണക്ഷൻ വീണ്ടും എൻക്രിപ്റ്റ് ചെയ്യുമ്പോൾ, നിങ്ങൾക്ക് മറ്റൊരു അറിയിപ്പ് ലഭിക്കും."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"മൊബൈൽ നെറ്റ്വർക്ക് സുരക്ഷാ ക്രമീകരണം"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"കൂടുതലറിയുക"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"മനസ്സിലായി"</string>
<string name="fcComplete" msgid="1080909484660507044">"ഫീച്ചർ കോഡ് പൂർണ്ണമാണ്."</string>
<string name="fcError" msgid="5325116502080221346">"കണക്ഷൻ പ്രശ്നം അല്ലെങ്കിൽ ഫീച്ചർ കോഡ് അസാധുവാണ്."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"ശരി"</string>
@@ -2156,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"ദിനചര്യ മോഡ് വിവരത്തെ കുറിച്ചുള്ള അറിയിപ്പ്"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"ബാറ്ററി സേവർ ഓണാക്കി"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"ബാറ്ററി ലൈഫ് വർദ്ധിപ്പിക്കാൻ ബാറ്ററി ഉപയോഗം കുറയ്ക്കുന്നു"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"ബാറ്ററി സേവർ ഓണാണ്"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"ബാറ്ററി ലൈഫ് വർദ്ധിപ്പിക്കാൻ ബാറ്ററി സേവർ ഓണാക്കിയിരിക്കുന്നു"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"ബാറ്ററി ലാഭിക്കൽ"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"ബാറ്ററി ലാഭിക്കൽ ഓഫാക്കിയിരിക്കുന്നു"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"ഫോണിൽ വേണ്ടത്ര ചാർജ് ഉണ്ട്. ഫീച്ചറുകൾക്ക് ഇനി നിയന്ത്രണമില്ല."</string>
@@ -2230,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"ഔദ്യോഗിക ആപ്പിലേക്ക് മാറണോ?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"സ്ഥാപനം ഔദ്യോഗിക ആപ്പുകളിൽ നിന്ന് കോളുകൾ ചെയ്യാൻ മാത്രമേ നിങ്ങളെ അനുവദിക്കുന്നുള്ളൂ"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"സ്ഥാപനം ഔദ്യോഗിക ആപ്പുകളിൽ നിന്ന് സന്ദേശമയയ്ക്കാൻ മാത്രമേ നിങ്ങളെ അനുവദിക്കുന്നുള്ളൂ"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"നിങ്ങളുടെ സ്വകാര്യ ഫോൺ ആപ്പിൽ നിന്ന് മാത്രമേ ഫോൺ വിളിക്കാനാകൂ. സ്വകാര്യ ഫോൺ ഉപയോഗിച്ചുള്ള കോളുകൾ നിങ്ങളുടെ സ്വകാര്യ കോൾ ചരിത്രത്തിലേക്ക് ചേർക്കും."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"നിങ്ങളുടെ സ്വകാര്യ സന്ദേശമയയ്ക്കൽ ആപ്പിൽ നിന്ന് മാത്രമേ നിങ്ങൾക്ക് SMS സന്ദേശങ്ങൾ അയയ്ക്കാനാകൂ."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"വ്യക്തിപരമായ ബ്രൗസർ ഉപയോഗിക്കുക"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"ഔദ്യോഗിക ബ്രൗസർ ഉപയോഗിക്കുക"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"കോൾ ചെയ്യുക"</string>
@@ -2413,6 +2401,10 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"ഔദ്യോഗികം 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"ടെസ്റ്റ്"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"കമ്മ്യൂണൽ"</string>
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"ഔദ്യോഗിക പ്രൊഫൈൽ"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"സ്വകാര്യ സ്പേസ്"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"ക്ലോൺ ചെയ്യുക"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"കമ്മ്യൂണൽ"</string>
<string name="redacted_notification_message" msgid="1520587845842228816">"സൂക്ഷ്മമായി കൈകാര്യം ചെയ്യേണ്ട അറിയിപ്പ് ഉള്ളടക്കം മറച്ചിരിക്കുന്നു"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"ആപ്പ് ഉള്ളടക്കം, അതിന്റെ സുരക്ഷയ്ക്കായി സ്ക്രീൻ പങ്കിടലിൽ നിന്ന് മറച്ചിരിക്കുന്നു"</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 45eacc0..afde064 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> секундын дараа"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: дамжуулагдаагүй"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: дамжуулагдаагүй"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Мобайл сүлжээний аюулгүй байдал"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Шифрлэлт, шифрлэгдээгүй сүлжээний мэдэгдэл"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"Төхөөрөмжийн ID-д хандсан"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"<xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>-д таныг <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> SIM-ээ ашиглаж байхад ойролцоох сүлжээ таны төхөөрөмжийн цор ганц дугаарыг (IMSI эсвэл IMEI) бүртгэсэн."</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"<xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>-д таныг <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> SIM-ээ ашиглаж байхад ойролцоох сүлжээ таны төхөөрөмжийн цор ганц дугаарыг (IMSI эсвэл IMEI) бүртгэсэн.\n\nЭнэ нь таны байршил, үйл ажиллагаа эсвэл таниулбарыг бүртгэсэн гэсэн үг юм. Энэ нь нийтлэг практик хэдий ч нууцлалд санаа зовнидог хүмүүсийн хувьд асуудал байж болох юм."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> шифрлэгдсэн сүлжээнд холбогдсон"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM холболт одоо илүү аюулгүй боллоо"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Шифрлэгдээгүй сүлжээнд холбогдсон"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Таныг <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM-ээ ашиглаж байхад дуудлага, мессеж, өгөгдөл одоогоор илүү эмзэг байна."</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Таныг <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM-ээ ашиглаж байхад дуудлага, мессеж, өгөгдөл одоогоор илүү эмзэг байна.\n\nТаны холболтыг дахин шифрлэсэн үед та өөр мэдэгдэл авна."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Мобайл сүлжээний аюулгүй байдлын тохиргоо"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Нэмэлт мэдээлэл авах"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"Ойлголоо"</string>
<string name="fcComplete" msgid="1080909484660507044">"Онцлог код дуусав."</string>
<string name="fcError" msgid="5325116502080221346">"Холболтын асуудал эсвэл буруу функцын код."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"ОК"</string>
@@ -371,8 +359,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Дэлгэцийн зургийг дарах"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Дэлгэцийн зургийг дарах боломжтой."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Урьдчилан үзэх, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"хаах"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"статус самбарыг идэвхгүй болгох болон өөрчлөх"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Апп нь статус самбарыг идэвхгүй болгох эсвэл систем дүрсийг нэмэх, хасах боломжтой."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"статусын хэсэг болох"</string>
@@ -2157,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Хэвшлийн горимын мэдээллийн мэдэгдэл"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Батарей хэмнэгчийг асаасан"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Батарейн ажиллах хугацааг уртасгахын тулд батарей ашиглалтыг багасгаж байна"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"Батарей хэмнэгч асаалттай байна"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"Батарей хэмнэгчийг батарейн ажиллах хугацааг уртасгахын тулд асаасан"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Батарей хэмнэгч"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Батарей хэмнэгчийг унтраалаа"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Утас хангалттай цэнэгтэй боллоо. Онцлогуудыг цаашид хязгаарлахгүй."</string>
@@ -2231,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Ажлын апп руу сэлгэх үү?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Танай байгууллага танд зөвхөн ажлын аппуудаас дуудлага хийхийг зөвшөөрдөг"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Танай байгууллага танд зөвхөн ажлын аппуудаас мессеж илгээхийг зөвшөөрдөг"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Та зөвхөн хувийн гар утасны аппаасаа утасны дуудлага хийх боломжтой. Хувийн гар утасны аппаас хийсэн дуудлагыг таны хувийн дуудлагын түүхэд нэмнэ."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"Та зөвхөн хувийн мессеж аппаасаа SMS мессеж илгээх боломжтой."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Хувийн хөтөч ашиглах"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Ажлын хөтөч ашиглах"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Залгах"</string>
@@ -2414,8 +2401,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Ажил 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Туршилт"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Нийтийн"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Ажлын профайл"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Хаалттай орон зай"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Клон"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Нийтийн"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Эмзэг мэдэгдлийн контентыг нуусан"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Аюулгүй байдлын улмаас аппын контентыг дэлгэц хуваалцахаас нуусан"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Хиймэл дагуулд автоматаар холбогдсон"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index c2a9c73..8e8d354 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="TIME_DELAY">{2}</xliff:g> सेकंदांनंतर <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: फॉरवर्ड केला नाही"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: फॉरवर्ड केला नाही"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"मोबाइल नेटवर्क सुरक्षा"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"एन्क्रिप्शन, एन्क्रिप्ट न केलेल्या नेटवर्कसाठी नोटिफिकेशन"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"डिव्हाइस आयडी अॅक्सेस करण्यात आला आहे"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"<xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> वाजता, जवळपासच्या नेटवर्कने तुमचे <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> सिम वापरत असताना तुमच्या डिव्हाइसचा युनिक आयडी (IMSI किंवा IMEI) रेकॉर्ड केला आहे"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"<xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> वाजता, जवळपासच्या नेटवर्कने तुमचे <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> सिम वापरत असताना तुमच्या डिव्हाइसचा युनिक आयडी (IMSI किंवा IMEI) रेकॉर्ड केला आहे.\n\nयाचा अर्थ असा आहे, की तुमचे स्थान, अॅक्टिव्हिटी किंवा ओळख लॉग करण्यात आली आहे. ही सामान्य प्रथा आहे, पण गोपनीयतेची काळजी असणाऱ्या लोकांसाठी ही समस्या असू शकते."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> या एन्क्रिप्ट केलेल्या नेटवर्कशी कनेक्ट केले आहे"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> सिमचे कनेक्शन आता आणखी सुरक्षित आहे"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"एन्क्रिप्ट न केलेल्या नेटवर्कशी कनेक्ट केले आहे"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"तुमचे <xliff:g id="NETWORK_NAME">%1$s</xliff:g> सिम वापरत असताना सध्या कॉल, मेसेज आणि डेटा या गोष्टी आणखी असुरक्षित आहेत"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"तुमचे <xliff:g id="NETWORK_NAME">%1$s</xliff:g> सिम वापरत असताना सध्या कॉल, मेसेज आणि डेटा या गोष्टी आणखी असुरक्षित आहेत.\n\nतुमचे कनेक्शन पुन्हा एन्क्रिप्ट केल्यावर, तुम्हाला आणखी एक नोटिफिकेशन मिळेल."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"मोबाइल नेटवर्क सुरक्षेसंबंधित सेटिंग्ज"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"अधिक जाणून घ्या"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"समजले"</string>
<string name="fcComplete" msgid="1080909484660507044">"वैशिष्ट्य कोड पूर्ण."</string>
<string name="fcError" msgid="5325116502080221346">"कनेक्शन समस्या किंवा अवैध फीचर कोड."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"ठीक"</string>
@@ -2156,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"दिनक्रम मोडची माहिती सूचना"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"बॅटरी सेव्हर सुरू केला आहे"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"बॅटरी लाइफ वाढवण्यासाठी बॅटरी वापर कमी करा"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"बॅटरी सेव्हर सुरू आहे"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"बॅटरी लाइफ वाढवण्यासाठी बॅटरी सेव्हर सुरू केले आहे"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"बॅटरी सेव्हर"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"बॅटरी सेव्हर बंद केलेला आहे"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"फोन पुरेसा चार्ज केलेला आहे. वैशिष्ट्ये मर्यादित नाहीत."</string>
@@ -2230,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"work app वर स्विच करायचे आहे का?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"तुमची संस्था तुम्हाला फक्त work app वरून कॉल करण्याची अनुमती देते"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"तुमची संस्था तुम्हाला फक्त work app वरून मेसेज पाठवण्याची अनुमती देते"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"तुम्ही तुमच्या वैयक्तिक फोन ॲपवरून फक्त फोन कॉल करू शकता. वैयक्तिक फोन वापरून केलेले कॉल हे तुमच्या वैयक्तिक कॉल इतिहासामध्ये जोडले जातील."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"तुम्ही तुमच्या वैयक्तिक Messages ॲप वरून फक्त एसएमएस मेसेज पाठवू शकता."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"वैयक्तिक ब्राउझर वापरा"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"कार्य ब्राउझर वापरा"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"कॉल करा"</string>
@@ -2413,6 +2401,10 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"ऑफिस ३"</string>
<string name="profile_label_test" msgid="9168641926186071947">"चाचणी"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"सामुदायिक"</string>
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"कार्य प्रोफाइल"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"खाजगी स्पेस"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"क्लोन"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"सामुदायिक"</string>
<string name="redacted_notification_message" msgid="1520587845842228816">"संवेदनशील नोटिफिकेशनचा आशय लपवलेला आहे"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"स्क्रीन शेअर करताना सुरक्षेसाठी अॅपमधील आशय लपवला आहे"</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 5e9ce27..fe4ab56 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> selepas <xliff:g id="TIME_DELAY">{2}</xliff:g> saat"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Tidak dimajukan"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Tidak dimajukan"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Keselamatan rangkaian mudah alih"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Penyulitan, pemberitahuan untuk rangkaian yang tidak disulitkan"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"ID peranti diakses"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"Pada <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, rangkaian berdekatan merekodkan ID unik peranti anda (IMSI atau IMEI) semasa menggunakan SIM <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> anda"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"Pada <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, rangkaian berdekatan merekodkan ID unik peranti anda (IMSI atau IMEI) semasa menggunakan SIM <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> anda.\n\nHal ini bermaksud bahawa lokasi, aktiviti atau identiti anda telah dilog. Amalan ini biasa dilakukan tetapi mungkin sukar dilakukan oleh pengguna yang bimbang tentang privasi."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Disambungkan kepada rangkaian <xliff:g id="NETWORK_NAME">%1$s</xliff:g> yang disulitkan"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"Sambungan SIM <xliff:g id="NETWORK_NAME">%1$s</xliff:g> kini lebih selamat"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Disambungkan kepada rangkaian yang tidak disulitkan"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Panggilan, mesej dan data lebih terdedah pada masa ini semasa menggunakan SIM <xliff:g id="NETWORK_NAME">%1$s</xliff:g> anda"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Panggilan, mesej dan data lebih terdedah pada masa ini semasa menggunakan SIM <xliff:g id="NETWORK_NAME">%1$s</xliff:g> anda.\n\nApabila sambungan anda disulitkan semula, anda akan menerima pemberitahuan lain."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Tetapan keselamatan rangkaian mudah alih"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Ketahui lebih lanjut"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"OK"</string>
<string name="fcComplete" msgid="1080909484660507044">"Kod ciri selesai."</string>
<string name="fcError" msgid="5325116502080221346">"Masalah sambungan atau kod ciri tidak sah."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -2156,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Pemberitahuan maklumat Mod Rutin"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Penjimat Bateri dihidupkan"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Mengurangkan penggunaan bateri untuk melanjutkan hayat bateri"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"Penjimat Bateri dihidupkan"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"Penjimat Bateri dihidupkan untuk melanjutkan hayat bateri"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Penjimat Bateri"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Penjimat Bateri dimatikan"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Cas telefon mencukupi. Ciri tidak lagi dihadkan."</string>
@@ -2230,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Beralih kepada apl kerja?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Organisasi anda hanya membenarkan anda membuat panggilan daripada apl kerja"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Organisasi anda hanya membenarkan anda menghantar mesej daripada apl kerja"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Anda hanya boleh membuat panggilan telefon daripada apl Telefon peribadi anda. Panggilan yang dibuat dengan apl Telefon peribadi akan ditambahkan pada sejarah panggilan peribadi anda."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"Anda hanya boleh menghantar mesej SMS daripada apl Messages peribadi anda."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Gunakan penyemak imbas peribadi"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Gunakan penyemak imbas kerja"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Panggil"</string>
@@ -2406,13 +2394,17 @@
<string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Reka letak papan kekunci ditetapkan kepada <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… Ketik untuk menukar reka letak."</string>
<string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Papan kekunci fizikal dikonfigurasikan"</string>
<string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Ketik untuk melihat papan kekunci"</string>
- <string name="profile_label_private" msgid="6463418670715290696">"Peribadi"</string>
+ <string name="profile_label_private" msgid="6463418670715290696">"Persendirian"</string>
<string name="profile_label_clone" msgid="769106052210954285">"Klon"</string>
<string name="profile_label_work" msgid="3495359133038584618">"Kerja"</string>
<string name="profile_label_work_2" msgid="4691533661598632135">"Kerja 2"</string>
<string name="profile_label_work_3" msgid="4834572253956798917">"Kerja 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Ujian"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Umum"</string>
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Profil kerja"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Ruang privasi"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Klon"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Umum"</string>
<string name="redacted_notification_message" msgid="1520587845842228816">"Kandungan pemberitahuan yang sensitif disembunyikan"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Kandungan apl disembunyikan daripada perkongsian skrin untuk keselamatan"</string>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index 81a79cf..5f5b0ab 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> နောက် <xliff:g id="TIME_DELAY">{2}</xliff:g> စက္ကန့်"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ထပ်ဆင့်မပို့နိုင်ပါ"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ထပ်ဆင့်မပို့နိုင်ပါ"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"မိုဘိုင်းကွန်ရက် လုံခြုံရေး"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"အသွင်ဝှက်ခြင်း၊ အသွင်ဝှက်မထားသော ကွန်ရက်များအတွက် အကြောင်းကြားချက်များ"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"စက် ID သုံးထားသည်"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"<xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> တွင် သင့် <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> ဆင်းမ်ကတ်ကို သုံးနေစဉ် အနီးရှိ ကွန်ရက်သည် စက်ပစ္စည်း၏ သီးသန့် ID (IMSI (သို့) IMEI) ကို မှတ်တမ်းတင်ထားသည်"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"<xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> တွင် သင့် <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> ဆင်းမ်ကတ်ကို သုံးနေစဉ် အနီးရှိ ကွန်ရက်သည် စက်ပစ္စည်း၏ သီးသန့် ID (IMSI (သို့) IMEI) ကို မှတ်တမ်းတင်ထားသည်။\n\nဆိုလိုသည်မှာ သင့်တည်နေရာ၊ လုပ်ဆောင်ချက် (သို့) အထောက်အထားကို မှတ်တမ်းတင်ထားသည်။ ၎င်းသည် သာမန်လုပ်ဆောင်မှုဖြစ်သော်လည်း ကိုယ်ရေးအချက်အလက်လုံခြုံမှုနှင့်ပတ်သက်၍ စိုးရိမ်သောသူများအတွက် ပြဿနာတစ်ခု ဖြစ်နိုင်သည်။"</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"အသွင်ဝှက်ထားသော ကွန်ရက် <xliff:g id="NETWORK_NAME">%1$s</xliff:g> သို့ ချိတ်ဆက်ထားသည်"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> ဆင်းမ်ကတ် ချိတ်ဆက်မှုသည် ယခု ပိုမိုလုံခြုံပါပြီ"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"အသွင်ဝှက်မထားသော ကွန်ရက်သို့ ချိတ်ဆက်ထားသည်"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"သင့် <xliff:g id="NETWORK_NAME">%1$s</xliff:g> ဆင်းမ်ကတ်ကို သုံးနေစဉ် ဖုန်းခေါ်ဆိုမှု၊ မက်ဆေ့ဂျ်နှင့် ဒေတာများသည် လက်ရှိတွင် ပိုမိုထိခိုက်လွယ်သည်"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"သင့် <xliff:g id="NETWORK_NAME">%1$s</xliff:g> ဆင်းမ်ကတ်ကို သုံးနေစဉ် ဖုန်းခေါ်ဆိုမှု၊ မက်ဆေ့ဂျ်နှင့် ဒေတာများသည် လက်ရှိတွင် ပိုမိုထိခိုက်လွယ်သည်။\n\nသင့်ချိတ်ဆက်မှုကို ထပ်မံအသွင်ဝှက်လိုက်သောအခါ အကြောင်းကြားချက်နောက်တစ်ခု ရရှိပါမည်။"</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"မိုဘိုင်းကွန်ရက် လုံခြုံရေး ဆက်တင်များ"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"ပိုမိုလေ့လာရန်"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"နားလည်ပြီ"</string>
<string name="fcComplete" msgid="1080909484660507044">"ပုံစံကုတ်ပြီးဆုံးသည်"</string>
<string name="fcError" msgid="5325116502080221346">"ဆက်သွယ်မှုဆိုင်ရာပြသနာ သို့မဟုတ် တရားမဝင်သောပုံစံကုတ်"</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -371,8 +359,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ဖန်သားပြင်ဓာတ်ပုံ ရိုက်ရန်"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ဖန်သားပြင်ပြသမှုကို ဓာတ်ပုံရိုက်နိုင်ပါသည်။"</string>
<string name="dream_preview_title" msgid="5570751491996100804">"<xliff:g id="DREAM_NAME">%1$s</xliff:g> အစမ်းကြည့်ခြင်း"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"ပယ်ရန်"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"အခြေအနေပြဘားအား အလုပ်မလုပ်ခိုင်းရန်သို့မဟုတ် မွမ်းမံရန်"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"အက်ပ်အား အခြေအနေပြ ဘားကို ပိတ်ခွင့် သို့မဟတ် စနစ် အိုင်ကွန်များကို ထည့်ခြင်း ဖယ်ရှားခြင်း ပြုလုပ်ခွင့် ပြုသည်။"</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"အခြေအနေပြ ဘားဖြစ်ပါစေ"</string>
@@ -2157,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"ပုံမှန်မုဒ်အတွက် အချက်အလက်ပြသည့် အကြောင်းကြားချက်"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"ဘက်ထရီ အားထိန်း ဖွင့်ထားသည်"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"ဘက်ထရီသက်တမ်း ပိုရှည်စေရန် ဘက်ထရီ အသုံးပြုမှု လျှော့ချခြင်း"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"‘ဘက်ထရီ အားထိန်း’ ဖွင့်ထားသည်"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"ဘက်ထရီ သက်တမ်းရှည်စေရန် ‘ဘက်ထရီ အားထိန်း’ ဖွင့်ထားသည်"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"ဘက်ထရီ အားထိန်း"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"ဘက်ထရီ အားထိန်းကို ပိတ်ထားသည်"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"ဖုန်းတွင် ဘက်ထရီအား အလုံအလောက် ရှိသည်။ လုပ်ဆောင်ချက်များကို ကန့်သတ်မထားတော့ပါ။"</string>
@@ -2231,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"အလုပ်သုံးအက်ပ်သို့ ပြောင်းမလား။"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"သင့်အဖွဲ့အစည်းသည် သင့်အား အလုပ်သုံးအက်ပ်များမှသာ ဖုန်းဆက်ခွင့်ပြုသည်"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"သင့်အဖွဲ့အစည်းသည် သင့်အား အလုပ်သုံးအက်ပ်များမှသာ မက်ဆေ့ဂျ်ပို့ခွင့်ပြုသည်"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"သင့်ကိုယ်ပိုင် ‘ဖုန်းအက်ပ်’ မှသာ ဖုန်းခေါ်ဆိုနိုင်သည်။ ကိုယ်ပိုင် ‘ဖုန်း’ ဖြင့် ပြုလုပ်သော ခေါ်ဆိုမှုများကို သင်၏ကိုယ်ပိုင် ခေါ်ဆိုမှုမှတ်တမ်းသို့ ထည့်ပါမည်။"</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"သင့်ကိုယ်ပိုင် Messages အက်ပ်မှသာ SMS မက်ဆေ့ဂျ်များကို ပို့နိုင်သည်။"</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"ကိုယ်ပိုင်ဘရောင်ဇာ သုံးရန်"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"အလုပ်သုံးဘရောင်ဇာ သုံးရန်"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"ဖုန်းဆက်ရန်"</string>
@@ -2414,8 +2401,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"အလုပ် ၃"</string>
<string name="profile_label_test" msgid="9168641926186071947">"စမ်းသပ်မှု"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"အများသုံး"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"အလုပ်ပရိုဖိုင်"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"သီးသန့်နေရာ"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"ပုံတူပွားရန်"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"အများသုံး"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"သတိထားရမည့် အကြောင်းကြားချက်ပါ အချက်အလက်ကို ဖျောက်ထားသည်"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"အက်ပ်အကြောင်းအရာသည် လုံခြုံရေးအတွက် မျက်နှာပြင် မျှဝေခြင်းမှ ဖျောက်ထားသည်"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"ဂြိုဟ်တုနှင့် အလိုအလျောက် ချိတ်ဆက်ထားသည်"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index efaae18..c4c705c 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> etter <xliff:g id="TIME_DELAY">{2}</xliff:g> sekunder"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Ikke viderekoblet"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Ikke viderekoblet"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Sikkerhet for mobilnettverk"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Kryptering, varsler for ukrypterte nettverk"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"Enhets-ID-en er lest"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"<xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> registrerte et nettverk i nærheten den unike ID-en (IMSI eller IMEI) til enheten din mens du brukte SIM-kortet fra <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"<xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> registrerte et nettverk i nærheten den unike ID-en (IMSI eller IMEI) til enheten din mens du brukte SIM-kortet fra <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>.\n\nDette betyr at posisjonen, aktiviteten eller identiteten din er registrert. Dette er en vanlig praksis, men kan være et problem for folk som er opptatt av personvern."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Koblet til det krypterte nettverket <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"Tilkoblingen til SIM-kortet fra <xliff:g id="NETWORK_NAME">%1$s</xliff:g> er sikrere nå"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Koblet til et ukryptert nettverk"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Anrop, meldinger og data er for øyeblikket mer sårbare ved bruk av SIM-kortet fra <xliff:g id="NETWORK_NAME">%1$s</xliff:g>."</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Anrop, meldinger og data er for øyeblikket mer sårbare ved bruk av SIM-kortet fra <xliff:g id="NETWORK_NAME">%1$s</xliff:g>.\n\nNår tilkoblingen er kryptert igjen, får du et nytt varsel."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Sikkerhetsinnstillinger for mobilnettverk"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Finn ut mer"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"Greit"</string>
<string name="fcComplete" msgid="1080909484660507044">"Funksjonskode utført."</string>
<string name="fcError" msgid="5325116502080221346">"Tilkoblingsproblem eller ugyldig funksjonskode."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -371,8 +359,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ta skjermdump"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Kan ikke ta en skjermdump av skjermen."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Forhåndsvisning, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"lukk"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"deaktivere eller endre statusfeltet"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Lar appen deaktivere statusfeltet eller legge til og fjerne systemikoner."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"vise appen i statusfeltet"</string>
@@ -2157,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Varsel med informasjon om rutinemodus"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Batterisparing er slått på"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Reduserer batteribruken for å forlenge batterilevetiden"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"Batterisparing er på"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"Batterisparing er slått på for å forlenge batterilevetiden"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Batterisparing"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Batterisparing er slått av"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Telefonen har nok batteri. Funksjoner begrenses ikke lenger."</string>
@@ -2231,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Vil du bytte til en jobbapp?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Organisasjonen din tillater bare at du ringer fra jobbapper"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Organisasjonen din tillater bare at du sender meldinger fra jobbapper"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Du kan bare ringe fra den personlige Telefon-appen din. Anrop via den personlige Telefon-appen legges til i den personlige anropsloggen din."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"Du kan bare sende SMS-meldinger fra den personlige Meldinger-appen din."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Bruk den personlige nettleseren"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Bruk jobbnettleseren"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Ring"</string>
@@ -2414,8 +2401,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Jobb 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Felles"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Jobbprofil"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Privat område"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Klon"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Felles"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Sensitivt varselinnhold er skjult"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Av sikkerhetsgrunner er appinnholdet skjult for skjermdelingen"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Automatisk tilkoblet satellitt"</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index cce955f..559f07a3 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -84,7 +84,7 @@
<string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"मोबाइल नेटवर्कमाथि पहुँच राख्न सकिएन"</string>
<string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"रुचाइएको नेटवर्क परिवर्तन गरी हेर्नुहोस्। परिवर्तन गर्न ट्याप गर्नुहोस्।"</string>
<string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"आपत्कालीन कल सेवा अनुपलब्ध छ"</string>
- <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"आपत्कालीन कलहरू गर्न मोबाइल नेटवर्क चाहिन्छ"</string>
+ <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"आपत्कालीन कलहरू गर्न मोबाइल नेटवर्क चाहिन्छ"</string>
<string name="notification_channel_network_alert" msgid="4788053066033851841">"अलर्टहरू"</string>
<string name="notification_channel_call_forward" msgid="8230490317314272406">"कल फर्वार्ड गर्ने सेवा"</string>
<string name="notification_channel_emergency_callback" msgid="54074839059123159">"आपत्कालीन कलब्याक मोड"</string>
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> पछि <xliff:g id="TIME_DELAY">{2}</xliff:g> सेकेन्ड"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: अगाडि बढाइएको छैन"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: अगाडि बढाइएको छैन"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"मोबाइल नेटवर्कको सुरक्षा"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"इन्क्रिप्सन, इन्क्रिप्ट नगरिएका नेटवर्कसम्बन्धी सूचना"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"डिभाइसको ID एक्सेस गरियो"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"तपाईंले आफ्नो <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> SIM प्रयोग गर्दै गर्दा तपाईंको डिभाइसको नजिकै रहेको एउटा नेटवर्कले <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> बजे तपाईंको डिभाइसको अद्वितीय ID रेकर्ड गरेको छ"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"तपाईंले आफ्नो <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> SIM प्रयोग गर्दै गर्दा तपाईंको डिभाइसको नजिकै रहेको एउटा नेटवर्कले <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> बजे तपाईंको डिभाइसको अद्वितीय ID रेकर्ड गरेको छ।\n\nयसको अर्थ तपाईंको लोकेसन, गतिविधि वा पहिचान लग गरिएको छ। यसो गर्नु सामान्य हो तर आफ्नो गोपनीयताका बारेमा चिन्ता लिने मान्छेहरूका लागि यो समस्याको विषय हुन सक्छ।"</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"इन्क्रिप्ट गरिएको नेटवर्क <xliff:g id="NETWORK_NAME">%1$s</xliff:g> मा कनेक्ट गरियो"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM को कनेक्सन अब सुरक्षित छ"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"इन्क्रिप्ट नगरिएको नेटवर्कमा कनेक्ट गरियो"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"हाल तपाईंले <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM प्रयोग गर्दै गर्दा कल, म्यासेज र डेटा एक्सेस गरिने जोखिम बढी छ"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"हाल तपाईंले <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM प्रयोग गर्दै गर्दा कल, म्यासेज र डेटा एक्सेस गरिने जोखिम बढी छ।\n\nतपाईंको कनेक्सन फेरि इन्क्रिप्ट गरिएपछि तपाईं अर्को सूचना प्राप्त गर्नु हुने छ।"</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"मोबाइल नेटवर्कको सुरक्षासम्बन्धी सेटिङ"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"थप जान्नुहोस्"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"बुझेँ"</string>
<string name="fcComplete" msgid="1080909484660507044">"विशेषता कोड पुरा भयो।"</string>
<string name="fcError" msgid="5325116502080221346">"जडान समस्या वा अमान्य सुविधा कोड।"</string>
<string name="httpErrorOk" msgid="6206751415788256357">"ठिक छ"</string>
@@ -371,8 +359,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"स्क्रिनसट लिनुहोस्"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"डिस्प्लेको स्क्रिनसट लिन सकिन्छ।"</string>
<string name="dream_preview_title" msgid="5570751491996100804">"प्रिभ्यू, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"हटाउनुहोस्"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"स्थिति पट्टिलाई अक्षम वा संशोधित गर्नुहोस्"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"स्थिति पट्टि असक्षम पार्न वा प्रणाली आइकनहरू थप्न र हटाउन एपलाई अनुमति दिन्छ।"</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"स्टाटस बार हुन दिनुहोस्"</string>
@@ -665,7 +652,7 @@
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"स्क्रिन लक प्रयोग गर्नुहोस्"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"जारी राख्न आफ्नो स्क्रिन लक हाल्नुहोस्"</string>
<string name="fingerprint_acquired_partial" msgid="4323789264604479684">"सेन्सरमा बेसरी थिच्नुहोस्"</string>
- <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"फिंगरप्रिन्ट पहिचान गर्न सकिएन। फेरि प्रयास गर्नुहोस्।"</string>
+ <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"फिंगरप्रिन्ट मिलेन। फेरि प्रयास गर्नुहोस्।"</string>
<string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"फिंगरप्रिन्ट सेन्सर सफा गरेर फेरि प्रयास गर्नुहोस्"</string>
<string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"सेन्सर सफा गरेर फेरि प्रयास गर्नुहोस्"</string>
<string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"सेन्सरमा बेसरी थिच्नुहोस्"</string>
@@ -677,8 +664,8 @@
<string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"हरेक पटक आफ्नो औँला थोरै यताउता सार्नुहोस्"</string>
<string-array name="fingerprint_acquired_vendor">
</string-array>
- <string name="fingerprint_error_not_match" msgid="4599441812893438961">"फिंगरप्रिन्ट पहिचान गर्न सकिएन"</string>
- <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"फिंगरप्रिन्ट पहिचान गर्न सकिएन"</string>
+ <string name="fingerprint_error_not_match" msgid="4599441812893438961">"फिंगरप्रिन्ट मिलेन"</string>
+ <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"फिंगरप्रिन्ट मिलेन"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"अनुहार पहिचान गर्न सकिएन। बरु फिंगरप्रिन्ट प्रयोग गर्नुहोस्।"</string>
<string name="fingerprint_authenticated" msgid="2024862866860283100">"फिंगरप्रिन्ट प्रमाणीकरण गरियो"</string>
<string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"अनुहार प्रमाणीकरण गरियो"</string>
@@ -1250,7 +1237,7 @@
<string name="whichImageCaptureApplicationNamed" msgid="8820702441847612202">"%1$s मार्फत छविलाई कैंद गर्नुहोस्"</string>
<string name="whichImageCaptureApplicationLabel" msgid="6505433734824988277">"छविलाई कैंद गर्नुहोस्"</string>
<string name="alwaysUse" msgid="3153558199076112903">"यस कार्यको लागि पूर्वनिर्धारितबाट प्रयोग गर्नुहोस्।"</string>
- <string name="use_a_different_app" msgid="4987790276170972776">"फरक एप प्रयोग गर्नुहोस्"</string>
+ <string name="use_a_different_app" msgid="4987790276170972776">"अर्को एप प्रयोग गर्नुहोस्"</string>
<string name="clearDefaultHintMsg" msgid="1325866337702524936">"प्रणाली सेटिङहरूमा पूर्वनिर्धारितलाई हटाउनुहोस् > एपहरू > डाउनलोड।"</string>
<string name="chooseActivity" msgid="8563390197659779956">"एउटा कार्यको चयन गर्नुहोस्"</string>
<string name="chooseUsbActivity" msgid="2096269989990986612">"USB उपकरणको लागि एउटा एप छान्नुहोस्"</string>
@@ -2157,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"दिनचर्या मोडको जानकारीमूलक सूचना"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"ब्याट्री सेभर अन गरिएको छ"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"ब्याट्रीको आयु बढाउन ब्याट्रीको खपत कम गरिँदै छ"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"ब्याट्री सेभर अन छ"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"ब्याट्रीको आयु बढाउन ब्याट्री सेभर अन गरिएको छ"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"ब्याट्री सेभर"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"ब्याट्री सेभर अफ गरियो"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"फोनमा पर्याप्त चार्ज छ। सुविधाहरूलाई अब उप्रान्त प्रतिबन्ध लगाइँदैन।"</string>
@@ -2231,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"कामसम्बन्धी एप प्रयोग गर्ने हो?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"तपाईंको सङ्गठनले तपाईंलाई कामसम्बन्धी एपहरूमार्फत मात्र कल गर्ने अनुमति दिएको छ"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"तपाईंको सङ्गठनले तपाईंलाई कामसम्बन्धी एपहरूमार्फत मात्र म्यासेज पठाउने अनुमति दिएको छ"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"तपाईं आफ्नो व्यक्तिगत फोन एपबाट मात्र फोन कल गर्न सक्नुहुन्छ। व्यक्तिगत फोन एपमार्फत गरिएका कलहरू तपाईंको व्यक्तिगत कल हिस्ट्रीमा राखिने छन्।"</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"तपाईं आफ्नो व्यक्तिगत Messages एपबाट मात्र SMS म्यासेजहरू पठाउन सक्नुहुन्छ।"</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"व्यक्तिगत ब्राउजर प्रयोग गर्नुहोस्"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"कार्य ब्राउजर प्रयोग गर्नुहोस्"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"कल गर्नुहोस्"</string>
@@ -2414,6 +2401,10 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"कार्य प्रोफाइल ३"</string>
<string name="profile_label_test" msgid="9168641926186071947">"परीक्षण"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"सामुदायिक"</string>
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"कार्य प्रोफाइल"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"निजी स्पेस"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"क्लोन"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"सामुदायिक"</string>
<string name="redacted_notification_message" msgid="1520587845842228816">"संवेदनशील सूचनासम्बन्धी सामग्री लुकाइएको छ"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"स्क्रिन सेयर गर्दा सुरक्षाका लागि एपमा भएको सामग्री लुकाइएको छ"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 40744589..5c393af 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> na <xliff:g id="TIME_DELAY">{2}</xliff:g> seconden"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: niet doorgeschakeld"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: niet doorgeschakeld"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Beveiliging van mobiel netwerk"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Versleuteling, meldingen voor niet-versleutelde netwerken"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"Toegang tot apparaat-ID gehad"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"Om <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> heeft een netwerk in de buurt de unieke ID van je apparaat (IMSI of IMEI) geregistreerd toen je je simkaart van <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> gebruikte"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"Om <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> heeft een netwerk in de buurt de unieke ID van je apparaat (IMSI of IMEI) geregistreerd toen je je simkaart van <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> gebruikte.\n\nDit betekent dat je locatie, activiteit of identiteit is geregistreerd. Dit is gebruikelijk, maar kan een probleem zijn voor mensen die zich zorgen maken over privacy."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Verbonden met versleuteld netwerk <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"De verbinding van de simkaart van <xliff:g id="NETWORK_NAME">%1$s</xliff:g> is nu beter beveiligd"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Verbonden met een niet-versleuteld netwerk"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Gesprekken, berichten en gegevens zijn op dit moment kwetsbaarder tijdens het gebruik van je simkaart van <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Gesprekken, berichten en gegevens zijn op dit moment kwetsbaarder tijdens het gebruik van je simkaart van <xliff:g id="NETWORK_NAME">%1$s</xliff:g>.\n\nAls je verbinding weer versleuteld is, krijg je opnieuw een melding."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Instellingen voor beveiliging van mobiel netwerk"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Meer informatie"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"OK"</string>
<string name="fcComplete" msgid="1080909484660507044">"Functiecode voltooid."</string>
<string name="fcError" msgid="5325116502080221346">"Verbindingsprobleem of ongeldige functiecode."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -2156,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Informatiemelding voor routinemodus"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Batterijbesparing staat aan"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Het batterijgebruik wordt beperkt om de batterijduur te verlengen"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"Batterijbesparing staat aan"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"Batterijbesparing is aangezet om de batterijduur te verlengen"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Batterijbesparing"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Batterijbesparing staat uit"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Telefoon is voldoende opgeladen. Functies worden niet meer beperkt."</string>
@@ -2230,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Overschakelen naar werk-app?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Je organisatie staat je alleen toe om te bellen vanuit werk-apps"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Je organisatie staat je alleen toe om berichten te sturen vanuit werk-apps"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Je kunt alleen bellen via je persoonlijke Telefoon-app. Gesprekken vanuit je persoonlijke Telefoon-app worden aan je persoonlijke gespreksgeschiedenis toegevoegd."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"Je kunt alleen sms-berichten sturen via je persoonlijke Berichten-app."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Persoonlijke browser gebruiken"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Werkbrowser gebruiken"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Bellen"</string>
@@ -2413,8 +2401,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Werk 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Gemeenschappelijk"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Werkprofiel"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Privégedeelte"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Kloon"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Gemeenschappelijk"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Content van gevoelige meldingen verborgen"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"App-content verborgen voor scherm delen vanwege beveiligingsrisico\'s"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Automatisch verbonden met satelliet"</string>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index 3ffc5b9..e6fa562 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> ସେକେଣ୍ଡ ପରେ"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ଫରୱାର୍ଡ କରାଯାଇନାହିଁ"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ଫର୍ୱର୍ଡ କରାଗଲା ନାହିଁ"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"ମୋବାଇଲ ନେଟୱାର୍କ ସୁରକ୍ଷା"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"ଏନକ୍ରିପସନ, ଏନକ୍ରିପ୍ଟ କରାଯାଇନଥିବା ନେଟୱାର୍କ ପାଇଁ ବିଜ୍ଞପ୍ତି"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"ଡିଭାଇସ ID ଆକ୍ସେସ କରାଯାଇଛି"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"ଆପଣଙ୍କ <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> ରେକର୍ଡ କରିବା ସମୟରେ <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>ରେ ଏକ ଆଖପାଖର ନେଟୱାର୍କ ଆପଣଙ୍କ ଡିଭାଇସର ସ୍ୱତନ୍ତ୍ର ID (IMSI କିମ୍ବା IMEI) ରେକର୍ଡ କରିଛି"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"ଆପଣଙ୍କ <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> SIM ବ୍ୟବହାର କରିବା ସମୟରେ <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>ରେ ଏକ ଆଖପାଖର ନେଟୱାର୍କ ଆପଣଙ୍କ ଡିଭାଇସର ସ୍ୱତନ୍ତ୍ର ID (IMSI କିମ୍ବା IMEI) ରେକର୍ଡ କରିଛି। \n\nଏହାର ଅର୍ଥ ହେଉଛି ଯେ ଆପଣଙ୍କ ଲୋକେସନ, କାର୍ଯ୍ୟକଳାପ କିମ୍ବା ପରିଚୟକୁ ଲଗ କରାଯାଇଛି। ଏହା ସାଧାରଣ ଅଭ୍ୟାସ ଅଟେ କିନ୍ତୁ ଗୋପନୀୟତା ବିଷୟରେ ଚିନ୍ତିତ ଲୋକମାନଙ୍କ ପାଇଁ ଏହା ଏକ ସମସ୍ୟା ହୋଇପାରେ।"</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"ଏନକ୍ରିପ୍ଟ କରାଯାଇଥିବା ନେଟୱାର୍କ <xliff:g id="NETWORK_NAME">%1$s</xliff:g> ସହ କନେକ୍ଟ କରାଯାଇଛି"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM କନେକ୍ସନ ବର୍ତ୍ତମାନ ଅଧିକ ସୁରକ୍ଷିତ ଅଟେ"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"ଏନକ୍ରିପ୍ଟ କରାଯାଇନଥିବା ନେଟୱାର୍କ ସହ କନେକ୍ଟ କରାଯାଇଛି"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"ଆପଣଙ୍କ <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM ବ୍ୟବହାର କରିବା ସମୟରେ କଲ, ମେସେଜ ଏବଂ ଡାଟା ବର୍ତ୍ତମାନ ଅଧିକ ଅସୁରକ୍ଷିତ ଅଟେ"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"ଆପଣଙ୍କ <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM ବ୍ୟବହାର କରିବା ସମୟରେ କଲ, ମେସେଜ ଏବଂ ଡାଟା ବର୍ତ୍ତମାନ ଅଧିକ ଅସୁରକ୍ଷିତ ଅଟେ।\n\nଆପଣଙ୍କ କନେକ୍ସନକୁ ପୁଣି ଏନକ୍ରିପ୍ଟ କରାଯିବା ସମୟରେ ଆପଣ ଅନ୍ୟ ଏକ ବିଜ୍ଞପ୍ତି ପାଇବେ।"</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"ମୋବାଇଲ ନେଟୱାର୍କ ସୁରକ୍ଷା ସେଟିଂସ"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"ଅଧିକ ଜାଣନ୍ତୁ"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"ବୁଝିଗଲି"</string>
<string name="fcComplete" msgid="1080909484660507044">"ଫିଚର୍ କୋଡ୍ ସମ୍ପୂର୍ଣ୍ଣ।"</string>
<string name="fcError" msgid="5325116502080221346">"ସଂଯୋଗରେ ସମସ୍ୟା କିମ୍ୱା ଅମାନ୍ୟ ଫିଚର୍ କୋଡ୍।"</string>
<string name="httpErrorOk" msgid="6206751415788256357">"ଠିକ ଅଛି"</string>
@@ -2156,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"ନିୟମିତ ମୋଡ୍ ସୂଚନା ବିଜ୍ଞପ୍ତି"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"ବେଟେରୀ ସେଭର ଚାଲୁ କରାଯାଇଛି"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"ବ୍ୟାଟେରୀ ଲାଇଫ ବଢ଼ାଇବା ପାଇଁ ବ୍ୟାଟେରୀ ବ୍ୟବହାର କମ୍ କରିବା"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"ବ୍ୟାଟେରୀ ସେଭର୍ ଚାଲୁ ଅଛି"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"ବେଟେରୀ ଲାଇଫକୁ ବଢ଼ାଇବା ପାଇଁ ବେଟେରୀ ସେଭରକୁ ଚାଲୁ କରାଯାଇଛି"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"ବେଟେରୀ ସେଭର"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"ବ୍ୟାଟେରୀ ସେଭର୍ ବନ୍ଦ ଅଛି"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"ଫୋନରେ ଯଥେଷ୍ଟ ଚାର୍ଜ ଅଛି। ଫିଚରଗୁଡ଼ିକ ଆଉ ପ୍ରତିବନ୍ଧିତ ନୁହେଁ।"</string>
@@ -2230,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"ୱାର୍କ ଆପକୁ ସୁଇଚ କରିବେ?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"ଆପଣଙ୍କ ସଂସ୍ଥା ଆପଣଙ୍କୁ କେବଳ ୱାର୍କ ଆପ୍ସରୁ କଲ କରିବାକୁ ଅନୁମତି ଦିଏ"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"ଆପଣଙ୍କ ସଂସ୍ଥା ଆପଣଙ୍କୁ କେବଳ ୱାର୍କ ଆପ୍ସରୁ ମେସେଜ ପଠାଇବା ପାଇଁ ଅନୁମତି ଦିଏ"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"ଆପଣ କେବଳ ଆପଣଙ୍କ ବ୍ୟକ୍ତିଗତ ଫୋନ ଆପରୁ ଫୋନ କଲ କରିପାରିବେ। ବ୍ୟକ୍ତିଗତ ଫୋନ ମାଧ୍ୟମରେ କରାଯାଇଥିବା କଲଗୁଡ଼ିକ ଆପଣଙ୍କ ବ୍ୟକ୍ତିଗତ କଲ ଇତିହାସରେ ଯୋଗ କରାଯିବ।"</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"ଆପଣ କେବଳ ଆପଣଙ୍କ ବ୍ୟକ୍ତିଗତ Messages ଆପରୁ SMS ମେସେଜଗୁଡ଼ିକ ପଠାଇପାରିବେ।"</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"ବ୍ୟକ୍ତିଗତ ବ୍ରାଉଜର୍ ବ୍ୟବହାର କରନ୍ତୁ"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"ୱାର୍କ ବ୍ରାଉଜର୍ ବ୍ୟବହାର କରନ୍ତୁ"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"କଲ କରନ୍ତୁ"</string>
@@ -2413,8 +2401,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"ୱାର୍କ 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"ଟେଷ୍ଟ"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"କମ୍ୟୁନାଲ"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"ୱାର୍କ ପ୍ରୋଫାଇଲ"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"ପ୍ରାଇଭେଟ ସ୍ପେସ"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"କ୍ଲୋନ"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"କମ୍ୟୁନାଲ"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"ସମ୍ୱେଦନଶୀଳ ବିଜ୍ଞପ୍ତି ବିଷୟବସ୍ତୁକୁ ଲୁଚାଯାଇଛି"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"ସୁରକ୍ଷା ପାଇଁ ସ୍କ୍ରିନ ସେୟାରରୁ ଆପ ବିଷୟବସ୍ତୁକୁ ଲୁଚାଯାଇଛି"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"ସାଟେଲାଇଟ ସହ ସ୍ୱତଃ କନେକ୍ଟ ହୋଇଛି"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 42a229e..e2586e6 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> ਸਕਿੰਟਾਂ ਬਾਅਦ"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ਅੱਗੇ ਨਹੀਂ ਭੇਜਿਆ ਗਿਆ"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ਅੱਗੇ ਨਹੀਂ ਭੇਜਿਆ ਗਿਆ"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"ਮੋਬਾਈਲ ਨੈੱਟਵਰਕ ਸੁਰੱਖਿਆ"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"ਇਨਕ੍ਰਿਪਸ਼ਨ, ਅਣ-ਇਨਕ੍ਰਿਪਟਡ ਨੈੱਟਵਰਕਾਂ ਲਈ ਸੂਚਨਾਵਾਂ"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"ਡੀਵਾਈਸ ਆਈਡੀ ਤੱਕ ਪਹੁੰਚ ਕੀਤੀ ਗਈ"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"<xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> ਵਜੇ, ਕਿਸੇ ਨਜ਼ਦੀਕੀ ਨੈੱਟਵਰਕ ਵੱਲੋਂ ਤੁਹਾਡੇ <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> ਸਿਮ ਦੀ ਵਰਤੋਂ ਕਰ ਕੇ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦੀ ਵਿਲੱਖਣ ਆਈਡੀ (IMSI ਜਾਂ IMEI) ਨੂੰ ਰਿਕਾਰਡ ਕੀਤਾ ਗਿਆ"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"<xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> ਵਜੇ, ਕਿਸੇ ਨਜ਼ਦੀਕੀ ਨੈੱਟਵਰਕ ਵੱਲੋਂ ਤੁਹਾਡੇ <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> ਸਿਮ ਦੀ ਵਰਤੋਂ ਕਰ ਕੇ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦੀ ਵਿਲੱਖਣ ਆਈਡੀ (IMSI ਜਾਂ IMEI) ਨੂੰ ਰਿਕਾਰਡ ਕੀਤਾ ਗਿਆ।\n\nਇਸ ਦਾ ਮਤਲਬ ਹੈ ਕਿ ਤੁਹਾਡਾ ਟਿਕਾਣਾ, ਸਰਗਰਮੀ ਜਾਂ ਪਛਾਣ ਨੂੰ ਲੌਗ ਕੀਤਾ ਗਿਆ ਹੈ। ਇਹ ਆਮ ਅਭਿਆਸ ਹੈ, ਪਰ ਪਰਦੇਦਾਰੀ ਬਾਰੇ ਚਿੰਤਤ ਲੋਕਾਂ ਲਈ ਇਹ ਸਮੱਸਿਆ ਹੋ ਸਕਦੀ ਹੈ।"</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"ਇਨਕ੍ਰਿਪਟਡ ਨੈੱਟਵਰਕ <xliff:g id="NETWORK_NAME">%1$s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ ਗਿਆ"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> ਸਿਮ ਕਨੈਕਸ਼ਨ ਹੁਣ ਜ਼ਿਆਦਾ ਸੁਰੱਖਿਅਤ ਹੈ"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"ਇਨਕ੍ਰਿਪਟਡ ਨੈੱਟਵਰਕ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ ਗਿਆ"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"ਫ਼ਿਲਹਾਲ ਤੁਹਾਡੇ <xliff:g id="NETWORK_NAME">%1$s</xliff:g> ਸਿਮ ਦੀ ਵਰਤੋਂ ਕਰਦੇ ਸਮੇਂ ਕਾਲਾਂ, ਸੁਨੇਹਿਆਂ ਅਤੇ ਡਾਟਾ ਜ਼ਿਆਦਾ ਖਤਰੇ ਵਿੱਚ ਹਨ"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"ਫ਼ਿਲਹਾਲ ਤੁਹਾਡੇ <xliff:g id="NETWORK_NAME">%1$s</xliff:g> ਸਿਮ ਦੀ ਵਰਤੋਂ ਕਰਦੇ ਸਮੇਂ ਕਾਲਾਂ, ਸੁਨੇਹਿਆਂ ਅਤੇ ਡਾਟਾ ਜ਼ਿਆਦਾ ਖਤਰੇ ਵਿੱਚ ਹਨ।\n\nਤੁਹਾਡਾ ਕਨੈਕਸ਼ਨ ਦੁਬਾਰਾ ਇਨਕ੍ਰਿਪਟਡ ਹੋਣ \'ਤੇ, ਤੁਹਾਨੂੰ ਹੋਰ ਸੂਚਨਾ ਪ੍ਰਾਪਤ ਹੋਵੇਗੀ।"</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"ਮੋਬਾਈਲ ਨੈੱਟਵਰਕ ਸੁਰੱਖਿਆ ਸੰਬੰਧੀ ਸੈਟਿੰਗਾਂ"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"ਹੋਰ ਜਾਣੋ"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"ਸਮਝ ਲਿਆ"</string>
<string name="fcComplete" msgid="1080909484660507044">"ਵਿਸ਼ੇਸ਼ਤਾ ਕੋਡ ਪੂਰਾ।"</string>
<string name="fcError" msgid="5325116502080221346">"ਕਨੈਕਸ਼ਨ ਸਮੱਸਿਆ ਜਾਂ ਅਵੈਧ ਵਿਸ਼ੇਸ਼ਤਾ ਕੋਡ।"</string>
<string name="httpErrorOk" msgid="6206751415788256357">"ਠੀਕ ਹੈ"</string>
@@ -843,8 +831,8 @@
<string name="permdesc_writeVerificationStateE2eeContactKeys" msgid="8453156829747427041">"ਐਪ ਨੂੰ ਹੋਰ ਐਪਾਂ ਦੀ ਮਲਕੀਅਤ ਵਾਲੀਆਂ E2EE ਸੰਪਰਕ ਕੁੰਜੀਆਂ ਦੀ ਪੁਸ਼ਟੀਕਰਨ ਸਥਿਤੀਆਂ ਨੂੰ ਅੱਪਡੇਟ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"ਪਾਸਵਰਡ ਨਿਯਮ ਸੈੱਟ ਕਰੋ"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"ਸਕ੍ਰੀਨ ਲਾਕ ਪਾਸਵਰਡਾਂ ਅਤੇ ਪਿੰਨ ਵਿੱਚ ਆਗਿਆ ਦਿੱਤੀ ਲੰਮਾਈ ਅਤੇ ਅੱਖਰਾਂ ਤੇ ਨਿਯੰਤਰਣ ਪਾਓ।"</string>
- <string name="policylab_watchLogin" msgid="7599669460083719504">"ਸਕ੍ਰੀਨ ਅਣਲਾਕ ਕਰਨ ਦੀਆਂ ਕੋਸ਼ਿਸ਼ਾਂ \'ਤੇ ਨਿਗਰਾਨੀ ਰੱਖੋ"</string>
- <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"ਸਕ੍ਰੀਨ ਨੂੰ ਅਣਲਾਕ ਕਰਦੇ ਹੋਏ ਟਾਈਪ ਕੀਤੇ ਗਲਤ ਪਾਸਵਰਡਾਂ ਦੀ ਸੰਖਿਆ ਦਾ ਨਿਰੀਖਣ ਕਰੋ ਅਤੇ ਟੈਬਲੈੱਟ ਨੂੰ ਲਾਕ ਕਰੋ ਜਾਂ ਟੈਬਲੈੱਟ ਦਾ ਸਾਰਾ ਡਾਟਾ ਮਿਟਾਓ, ਜੇਕਰ ਬਹੁਤ ਜ਼ਿਆਦਾ ਗਲਤ ਪਾਸਵਰਡ ਟਾਈਪ ਕੀਤੇ ਹਨ।"</string>
+ <string name="policylab_watchLogin" msgid="7599669460083719504">"ਸਕ੍ਰੀਨ ਅਣਲਾਕ ਕਰਨ ਦੀਆਂ ਕੋਸ਼ਿਸ਼ਾਂ \'ਤੇ ਨਿਗਰਾਨੀ ਰੱਖਣਾ"</string>
+ <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"ਸਕ੍ਰੀਨ ਨੂੰ ਅਣਲਾਕ ਕਰਦੇ ਹੋਏ ਟਾਈਪ ਕੀਤੇ ਗਲਤ ਪਾਸਵਰਡਾਂ ਦੀ ਸੰਖਿਆ ਦਾ ਨਿਰੀਖਣ ਕਰਨਾ ਅਤੇ ਬਹੁਤ ਜ਼ਿਆਦਾ ਵਾਰ ਗਲਤ ਪਾਸਵਰਡ ਟਾਈਪ ਕੀਤੇ ਜਾਣ \'ਤੇ ਟੈਬਲੈੱਟ ਨੂੰ ਲਾਕ ਕਰਨਾ ਜਾਂ ਟੈਬਲੈੱਟ ਦਾ ਸਾਰਾ ਡਾਟਾ ਮਿਟਾਉਣਾ।"</string>
<string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"ਸਕ੍ਰੀਨ ਨੂੰ ਅਣਲਾਕ ਕਰਦੇ ਹੋਏ ਟਾਈਪ ਕੀਤੇ ਗਲਤ ਪਾਸਵਰਡਾਂ ਦੀ ਸੰਖਿਆ ਦਾ ਨਿਰੀਖਣ ਕਰੋ ਅਤੇ ਆਪਣੇ Android TV ਡੀਵਾਈਸ ਨੂੰ ਲਾਕ ਕਰੋ ਜਾਂ ਆਪਣੇ Android TV ਡੀਵਾਈਸ ਦਾ ਸਾਰਾ ਡਾਟਾ ਮਿਟਾਓ, ਜੇ ਬਹੁਤ ਜ਼ਿਆਦਾ ਗਲਤ ਪਾਸਵਰਡ ਟਾਈਪ ਕੀਤੇ ਹਨ।"</string>
<string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"ਸਕ੍ਰੀਨ ਨੂੰ ਅਣਲਾਕ ਕਰਦੇ ਸਮੇਂ ਟਾਈਪ ਕੀਤੇ ਗਲਤ ਪਾਸਵਰਡਾਂ ਦੀ ਸੰਖਿਆ ਦੀ ਨਿਗਰਾਨੀ ਕਰੋ ਅਤੇ ਜੇ ਬਹੁਤ ਜ਼ਿਆਦਾ ਗਲਤ ਪਾਸਵਰਡ ਟਾਈਪ ਕੀਤੇ ਹਨ, ਤਾਂ ਵਾਹਨ ਆਡੀਓ ਸਿਸਟਮ ਨੂੰ ਲਾਕ ਕਰੋ ਜਾਂ ਵਾਹਨ ਆਡੀਓ ਸਿਸਟਮ ਦਾ ਸਾਰਾ ਡਾਟਾ ਮਿਟਾਓ।"</string>
<string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"ਸਕ੍ਰੀਨ ਨੂੰ ਅਣਲਾਕ ਕਰਦੇ ਸਮੇਂ ਟਾਈਪ ਕੀਤੇ ਗਲਤ ਪਾਸਵਰਡਾਂ ਦੀ ਗਿਣਤੀ ਦੀ ਨਿਗਰਾਨੀ ਕਰੋ ਅਤੇ ਜੇ ਬਹੁਤ ਜ਼ਿਆਦਾ ਗਲਤ ਪਾਸਵਰਡ ਟਾਈਪ ਕੀਤੇ ਹਨ, ਤਾਂ ਫ਼ੋਨ ਨੂੰ ਲਾਕ ਕਰੋ ਜਾਂ ਫ਼ੋਨ ਦਾ ਸਾਰਾ ਡਾਟਾ ਮਿਟਾਓ।"</string>
@@ -856,8 +844,8 @@
<string name="policydesc_resetPassword" msgid="4626419138439341851">"ਸਕ੍ਰੀਨ ਲਾਕ ਬਦਲੋ।"</string>
<string name="policylab_forceLock" msgid="7360335502968476434">"ਸਕ੍ਰੀਨ ਲਾਕ ਕਰੋ"</string>
<string name="policydesc_forceLock" msgid="1008844760853899693">"ਸਕ੍ਰੀਨ ਦਾ ਕਿਵੇਂ ਅਤੇ ਕਦੋਂ ਲਾਕ ਹੋਣਾ ਕੰਟਰੋਲ ਕਰੋ।"</string>
- <string name="policylab_wipeData" msgid="1359485247727537311">"ਸਾਰਾ ਡਾਟਾ ਮਿਟਾਓ"</string>
- <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"ਫੈਕਟਰੀ ਡਾਟਾ ਰੀਸੈੱਟ ਕਰ ਕੇ ਚਿਤਾਵਨੀ ਤੋਂ ਬਿਨਾਂ ਟੈਬਲੈੱਟ ਦਾ ਡਾਟਾ ਮਿਟਾਓ।"</string>
+ <string name="policylab_wipeData" msgid="1359485247727537311">"ਸਾਰਾ ਡਾਟਾ ਮਿਟਾਉਣਾ"</string>
+ <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"ਫੈਕਟਰੀ ਡਾਟਾ ਰੀਸੈੱਟ ਕਰ ਕੇ ਚਿਤਾਵਨੀ ਤੋਂ ਬਿਨਾਂ ਟੈਬਲੈੱਟ ਦਾ ਡਾਟਾ ਮਿਟਾਉਣਾ।"</string>
<string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"ਫੈਕਟਰੀ ਡਾਟਾ ਰੀਸੈੱਟ ਕਰਕੇ ਬਿਨਾਂ ਚਿਤਾਵਨੀ ਦੇ ਤੁਹਾਡੇ Android TV ਡੀਵਾਈਸ ਦਾ ਡਾਟਾ ਮਿਟਾ ਦਿੱਤਾ ਜਾਂਦਾ ਹੈ।"</string>
<string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"ਫੈਕਟਰੀ ਡਾਟਾ ਰੀਸੈੱਟ ਕਰਕੇ ਚਿਤਾਵਨੀ ਤੋਂ ਬਿਨਾਂ ਵਾਹਨ ਆਡੀਓ ਸਿਸਟਮ ਦਾ ਡਾਟਾ ਮਿਟਾਓ।"</string>
<string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"ਫੈਕਟਰੀ ਡਾਟਾ ਰੀਸੈੱਟ ਕਰ ਕੇ ਚਿਤਾਵਨੀ ਤੋਂ ਬਿਨਾਂ ਫ਼ੋਨ ਦਾ ਡਾਟਾ ਮਿਟਾਓ।"</string>
@@ -1249,7 +1237,7 @@
<string name="whichImageCaptureApplicationNamed" msgid="8820702441847612202">"%1$s ਨਾਲ ਚਿਤਰ ਕੈਪਚਰ ਕਰੋ"</string>
<string name="whichImageCaptureApplicationLabel" msgid="6505433734824988277">"ਚਿਤਰ ਕੈਪਚਰ ਕਰੋ"</string>
<string name="alwaysUse" msgid="3153558199076112903">"ਇਸ ਕਾਰਵਾਈ ਲਈ ਪੂਰਵ-ਨਿਰਧਾਰਤ ਵਰਤੋ।"</string>
- <string name="use_a_different_app" msgid="4987790276170972776">"ਇੱਕ ਵੱਖਰਾ ਖਾਤਾ ਵਰਤੋ"</string>
+ <string name="use_a_different_app" msgid="4987790276170972776">"ਕੋਈ ਵੱਖਰੀ ਐਪ ਵਰਤੋ"</string>
<string name="clearDefaultHintMsg" msgid="1325866337702524936">"ਸਿਸਟਮ ਸੈਟਿੰਗਾਂ > ਐਪਾਂ > ਡਾਊਨਲੋਡ ਕੀਤਿਆਂ ਵਿੱਚ ਪੂਰਵ-ਨਿਰਧਾਰਤ ਹਟਾਓ।"</string>
<string name="chooseActivity" msgid="8563390197659779956">"ਇੱਕ ਕਾਰਵਾਈ ਚੁਣੋ"</string>
<string name="chooseUsbActivity" msgid="2096269989990986612">"USB ਡੀਵਾਈਸ ਲਈ ਇੱਕ ਐਪ ਚੁਣੋ"</string>
@@ -2156,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"ਨਿਯਮਬੱਧ ਮੋਡ ਦੀ ਜਾਣਕਾਰੀ ਵਾਲੀ ਸੂਚਨਾ"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"ਬੈਟਰੀ ਸੇਵਰ ਚਾਲੂ ਹੈ"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"ਬੈਟਰੀ ਲਾਈਫ਼ ਵਧਾਉਣ ਲਈ ਬੈਟਰੀ ਵਰਤੋਂ ਨੂੰ ਘਟਾਉਣਾ"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"ਬੈਟਰੀ ਸੇਵਰ ਚਾਲੂ ਹੈ"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"ਬੈਟਰੀ ਲਾਈਫ਼ ਵਧਾਉਣ ਲਈ ਬੈਟਰੀ ਸੇਵਰ ਚਾਲੂ ਕੀਤਾ ਗਿਆ ਹੈ"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"ਬੈਟਰੀ ਸੇਵਰ"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"ਬੈਟਰੀ ਸੇਵਰ ਬੰਦ ਕੀਤਾ ਗਿਆ"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"ਫ਼ੋਨ ਲੋੜੀਂਦਾ ਚਾਰਜ ਹੈ। ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਹੁਣ ਪ੍ਰਤਿਬੰਧਿਤ ਨਹੀਂ ਹਨ।"</string>
@@ -2230,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"ਕੀ ਕੰਮ ਸੰਬੰਧੀ ਐਪ \'ਤੇ ਸਵਿੱਚ ਕਰਨਾ ਹੈ?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"ਤੁਹਾਡੀ ਸੰਸਥਾ ਤੁਹਾਨੂੰ ਸਿਰਫ਼ ਕੰਮ ਸੰਬੰਧੀ ਐਪਾਂ ਤੋਂ ਕਾਲਾਂ ਕਰਨ ਦਿੰਦੀ ਹੈ"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"ਤੁਹਾਡੀ ਸੰਸਥਾ ਤੁਹਾਨੂੰ ਸਿਰਫ਼ ਕੰਮ ਸੰਬੰਧੀ ਐਪਾਂ ਤੋਂ ਹੀ ਸੁਨੇਹੇ ਭੇਜਣ ਦਿੰਦੀ ਹੈ"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"ਤੁਸੀਂ ਸਿਰਫ਼ ਆਪਣੀ ਨਿੱਜੀ ਫ਼ੋਨ ਐਪ ਤੋਂ ਫ਼ੋਨ ਕਾਲਾਂ ਕਰ ਸਕਦੇ ਹੋ। ਨਿੱਜੀ ਫ਼ੋਨ ਤੋਂ ਕੀਤੀਆਂ ਕਾਲਾਂ ਤੁਹਾਡੇ ਨਿੱਜੀ ਕਾਲ ਇਤਿਹਾਸ ਵਿੱਚ ਸ਼ਾਮਲ ਕੀਤੀਆਂ ਜਾਣਗੀਆਂ।"</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"ਤੁਸੀਂ ਸਿਰਫ਼ ਆਪਣੀ ਨਿੱਜੀ ਸੁਨੇਹਾ ਐਪ ਤੋਂ SMS ਸੁਨੇਹੇ ਭੇਜ ਸਕਦੇ ਹੋ।"</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"ਨਿੱਜੀ ਬ੍ਰਾਊਜ਼ਰ ਵਰਤੋ"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"ਕੰਮ ਸੰਬੰਧੀ ਬ੍ਰਾਊਜ਼ਰ ਵਰਤੋ"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"ਕਾਲ ਕਰੋ"</string>
@@ -2406,15 +2394,18 @@
<string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"ਕੀ-ਬੋਰਡ ਦਾ ਖਾਕਾ <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g> \'ਤੇ ਸੈੱਟ ਹੈ… ਬਦਲਣ ਲਈ ਟੈਪ ਕਰੋ।"</string>
<string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"ਭੌਤਿਕ ਕੀ-ਬੋਰਡਾਂ ਦਾ ਸੰਰੂਪਣ ਕੀਤਾ ਗਿਆ"</string>
<string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"ਕੀ-ਬੋਰਡਾਂ ਨੂੰ ਦੇਖਣ ਲਈ ਟੈਪ ਕਰੋ"</string>
- <string name="profile_label_private" msgid="6463418670715290696">"ਨਿੱਜੀ"</string>
+ <string name="profile_label_private" msgid="6463418670715290696">"ਪ੍ਰਾਈਵੇਟ"</string>
<string name="profile_label_clone" msgid="769106052210954285">"ਕਲੋਨ"</string>
<string name="profile_label_work" msgid="3495359133038584618">"ਕਾਰਜ"</string>
<string name="profile_label_work_2" msgid="4691533661598632135">"ਕੰਮ ਸੰਬੰਧੀ 2"</string>
<string name="profile_label_work_3" msgid="4834572253956798917">"ਕੰਮ ਸੰਬੰਧੀ 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"ਜਾਂਚ"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"ਭਾਈਚਾਰਕ"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"ਪ੍ਰਾਈਵੇਟ ਸਪੇਸ"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"ਕਲੋਨ"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"ਭਾਈਚਾਰਕ"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"ਲੁਕੀ ਹੋਈ ਸੰਵੇਦਨਸ਼ੀਲ ਸੂਚਨਾ ਸਮੱਗਰੀ"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"ਐਪ ਸਮੱਗਰੀ ਨੂੰ ਸੁਰੱਖਿਆ ਲਈ ਸਕ੍ਰੀਨ ਸਾਂਝਾਕਰਨ ਤੋਂ ਲੁਕਾਇਆ ਗਿਆ ਹੈ"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"ਸੈਟੇਲਾਈਟ ਨਾਲ ਸਵੈ-ਕਨੈਕਟ ਹੋਇਆ"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 2dccba9..d5c8d76 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -155,31 +155,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> po <xliff:g id="TIME_DELAY">{2}</xliff:g> sekundach"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: nieprzekierowane"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: nieprzekierowane"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Bezpieczeństwo sieci komórkowej"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Szyfrowanie, powiadomienia dotyczące niezaszyfrowanych sieci"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"Uzyskano dostęp do identyfikatora urządzenia"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"O godzinie <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> pobliska sieć zarejestrowała unikalny identyfikator Twojego urządzenia (IMSI lub IMEI) podczas korzystania z karty SIM <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"O godzinie <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> pobliska sieć zarejestrowała unikalny identyfikator Twojego urządzenia (IMSI lub IMEI) podczas korzystania z karty SIM <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>.\n\nOznacza to, że zarejestrowano Twoją lokalizację, aktywność lub tożsamość. Jest to powszechna praktyka, ale może stanowić problem dla osób dbających o prywatność."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Połączono z szyfrowaną siecią <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"Połączenie SIM <xliff:g id="NETWORK_NAME">%1$s</xliff:g> jest teraz bezpieczniejsze"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Połączono z niezaszyfrowaną siecią"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Połączenia, wiadomości i dane są obecnie bardziej podatne na ataki podczas korzystania z karty SIM <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Połączenia, wiadomości i dane są obecnie bardziej podatne na ataki podczas korzystania z karty SIM <xliff:g id="NETWORK_NAME">%1$s</xliff:g>.\n\nGdy połączenie zostanie ponownie zaszyfrowane, otrzymasz kolejne powiadomienie."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Ustawienia bezpieczeństwa sieci komórkowej"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Więcej informacji"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"OK"</string>
<string name="fcComplete" msgid="1080909484660507044">"Wykonano kod funkcji."</string>
<string name="fcError" msgid="5325116502080221346">"Problem z połączeniem lub nieprawidłowy kod funkcji."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -373,8 +361,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Robienie zrzutu ekranu"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Może robić zrzuty ekranu wyświetlacza."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Podgląd, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"zamknij"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"wyłączanie lub zmienianie paska stanu"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Pozwala aplikacji na wyłączanie paska stanu oraz dodawanie i usuwanie ikon systemowych."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"działanie jako pasek stanu"</string>
@@ -2159,6 +2146,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Powiadomienie z informacją o trybie rutynowym"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Oszczędzanie baterii jest włączone"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Ograniczam wykorzystanie baterii, aby przedłużyć jej żywotność"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"Oszczędzanie baterii jest włączone"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"Oszczędzanie baterii jest włączone, aby wydłużyć jej żywotność"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Oszczędzanie baterii"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Oszczędzanie baterii zostało wyłączone"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Telefon jest wystarczająco naładowany. Funkcje nie są już ograniczone."</string>
@@ -2233,10 +2222,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Przełączyć na aplikację służbową?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Twoja organizacja zezwala na nawiązywanie połączeń tylko z aplikacji służbowych"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Twoja organizacja zezwala na wysyłanie wiadomości tylko z aplikacji służbowych"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Połączenia telefoniczne możesz wykonywać wyłącznie za pomocą osobistej aplikacji Telefon. Takie połączenia zostaną dodane do Twojej osobistej historii połączeń."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"Wiadomości SMS możesz wysyłać wyłącznie z osobistej aplikacji Wiadomości."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Użyj przeglądarki osobistej"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Użyj przeglądarki służbowej"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Zadzwoń"</string>
@@ -2416,6 +2403,10 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Służbowy 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Testowy"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Wspólny"</string>
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Profil służbowy"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Przestrzeń prywatna"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Klon"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Wspólny"</string>
<string name="redacted_notification_message" msgid="1520587845842228816">"Treść poufnego powiadomienia została ukryta"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Ze względów bezpieczeństwa zawartość aplikacji jest niewidoczna podczas udostępniania ekranu"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 8a03716..4d9e208 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -154,31 +154,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> após <xliff:g id="TIME_DELAY">{2}</xliff:g> segundos"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Não encaminhado"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Não encaminhado"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Segurança de rede móvel"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Criptografia, notificações para redes não criptografadas"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"ID do dispositivo acessado"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"Às <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, uma rede próxima registrou o ID exclusivo do seu dispositivo (IMSI ou IMEI) enquanto usava seu chip da <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"Às <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, uma rede próxima registrou o ID exclusivo do seu dispositivo (IMSI ou IMEI) usando seu chip da <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>.\n\nIsso significa que sua localização, atividade ou identidade foram registradas. Essa é uma prática comum, mas pode ser um problema para pessoas preocupadas com a privacidade."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Conectado à rede criptografada <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"A conexão do chip da <xliff:g id="NETWORK_NAME">%1$s</xliff:g> está mais segura agora"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Conectado à rede não criptografada"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Suas ligações, mensagens e dados estão mais vulneráveis no momento ao usar seu chip da <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Ligações, mensagens e dados estão mais vulneráveis no momento ao usar seu chip da <xliff:g id="NETWORK_NAME">%1$s</xliff:g>.\n\nQuando a conexão for criptografada novamente, você vai receber outra notificação."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Configurações de segurança de rede móvel"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Saiba mais"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"Entendi"</string>
<string name="fcComplete" msgid="1080909484660507044">"Código de recurso concluído."</string>
<string name="fcError" msgid="5325116502080221346">"Problema de conexão ou código de recurso inválido."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -372,8 +360,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Fazer uma captura de tela"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Pode fazer uma captura de tela."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Visualização, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"dispensar"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"desativar ou modificar a barra de status"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Permite que o app desative a barra de status ou adicione e remova ícones do sistema."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"ser a barra de status"</string>
@@ -1224,7 +1211,7 @@
<string name="not_selected" msgid="410652016565864475">"não selecionado"</string>
<string name="rating_label" msgid="1837085249662154601">"{rating,plural, =1{1 de {max} estrelas}one{# de {max} estrelas}many{# de {max} estrelas}other{# de {max} estrelas}}"</string>
<string name="in_progress" msgid="2149208189184319441">"em andamento"</string>
- <string name="whichApplication" msgid="5432266899591255759">"Complete a ação usando"</string>
+ <string name="whichApplication" msgid="5432266899591255759">"Concluir a ação usando"</string>
<string name="whichApplicationNamed" msgid="6969946041713975681">"Concluir a ação usando %1$s"</string>
<string name="whichApplicationLabel" msgid="7852182961472531728">"Concluir ação"</string>
<string name="whichViewApplication" msgid="5733194231473132945">"Abrir com"</string>
@@ -2158,6 +2145,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Notificação de informação do modo rotina"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Economia de bateria ativada"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Reduzindo o uso da bateria para prolongar a duração dela"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"A Economia de bateria está ativada"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"A Economia de bateria está ativada para prolongar a duração da carga"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Economia de bateria"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"\"Economia de bateria\" desativada"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Não há carga suficiente no smartphone. Os recursos não estão mais restritos."</string>
@@ -2232,10 +2221,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Trocar para o app de trabalho?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Sua organização só permite fazer ligações usando apps de trabalho"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Sua organização só permite o envio de mensagens usando apps de trabalho"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"É possível fazer ligações apenas usando seu app Telefone pessoal. Essas ligações telefônicas serão adicionadas ao seu histórico pessoal."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"É possível enviar mensagens SMS apenas usando seu app Mensagens pessoal."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Usar o navegador pessoal"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Usar o navegador de trabalho"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Ligar"</string>
@@ -2415,8 +2402,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Trabalho 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Teste"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Público"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Perfil de trabalho"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Espaço privado"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Clone"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Público"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Conteúdo de notificação sensível oculto"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Conteúdo do app oculto no compartilhamento de tela por motivos de segurança"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Conectado automaticamente ao satélite"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 5b130bc..2074d1e 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -154,31 +154,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> após <xliff:g id="TIME_DELAY">{2}</xliff:g> segundos"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Não reencaminhado"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Não reencaminhado"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Segurança de redes móveis"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Encriptação e notificações para redes não encriptadas"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"ID do dispositivo acedido"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"À(s) <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, uma rede próxima registou o ID exclusivo do seu dispositivo (IMSI ou IMEI) enquanto usava o seu SIM <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"À(s) <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, uma rede próxima registou o ID exclusivo do seu dispositivo (IMSI ou IMEI) enquanto usava o seu SIM <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>.\n\nIsto significa que a sua localização, atividade ou identidade foram registadas. Esta é uma prática comum, mas pode ser um problema para pessoas preocupadas com a privacidade."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Ligação estabelecida à rede <xliff:g id="NETWORK_NAME">%1$s</xliff:g> encriptada"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"Agora, a ligação ao SIM <xliff:g id="NETWORK_NAME">%1$s</xliff:g> é mais segura"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Ligação estabelecida a uma rede não encriptada"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"As chamadas, as mensagens e os dados são atualmente mais vulneráveis quando usa o SIM <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"As chamadas, as mensagens e os dados são atualmente mais vulneráveis quando usa o SIM <xliff:g id="NETWORK_NAME">%1$s</xliff:g>.\n\nQuando a sua ligação for novamente encriptada, recebe outra notificação."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Definições da segurança de redes móveis"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Saber mais"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"OK"</string>
<string name="fcComplete" msgid="1080909484660507044">"Código de funcionalidade completo."</string>
<string name="fcError" msgid="5325116502080221346">"Problema de ligação ou código de funcionalidade inválido."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -2157,6 +2145,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Notificação de informações do Modo rotina"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Poupança de bateria ativada"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Reduzir a utilização da bateria para prolongar a autonomia da mesma"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"Poupança de bateria ativada"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"A Poupança de bateria está ativada para prolongar a autonomia da bateria"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Poupança de bateria"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"A Poupança de bateria está desativada"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"O telemóvel tem carga suficiente. As funcionalidades já não estão restritas."</string>
@@ -2231,10 +2221,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Mudar para a app de trabalho?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"A sua organização só lhe permite fazer chamadas a partir de apps de trabalho"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"A sua organização só lhe permite enviar mensagens a partir de apps de trabalho"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Só pode fazer chamadas telefónicas a partir da sua app Telefone pessoal. As chamadas feitas com a app Telefone pessoal são adicionadas ao seu histórico de chamadas pessoal."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"Só pode enviar mensagens SMS a partir da sua app Mensagens pessoal."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Usar navegador pessoal"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Usar navegador de trabalho"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Ligar"</string>
@@ -2414,8 +2402,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Trabalho 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Teste"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Comum"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Perfil de trabalho"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Espaço privado"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Clone"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Comum"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Conteúdo das notificações sensíveis ocultado"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Conteúdo da app ocultado da partilha de ecrã por motivos de segurança"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Ligação de satélite estabelecida automaticamente"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 8a03716..4d9e208 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -154,31 +154,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> após <xliff:g id="TIME_DELAY">{2}</xliff:g> segundos"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Não encaminhado"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Não encaminhado"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Segurança de rede móvel"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Criptografia, notificações para redes não criptografadas"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"ID do dispositivo acessado"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"Às <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, uma rede próxima registrou o ID exclusivo do seu dispositivo (IMSI ou IMEI) enquanto usava seu chip da <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"Às <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, uma rede próxima registrou o ID exclusivo do seu dispositivo (IMSI ou IMEI) usando seu chip da <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>.\n\nIsso significa que sua localização, atividade ou identidade foram registradas. Essa é uma prática comum, mas pode ser um problema para pessoas preocupadas com a privacidade."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Conectado à rede criptografada <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"A conexão do chip da <xliff:g id="NETWORK_NAME">%1$s</xliff:g> está mais segura agora"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Conectado à rede não criptografada"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Suas ligações, mensagens e dados estão mais vulneráveis no momento ao usar seu chip da <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Ligações, mensagens e dados estão mais vulneráveis no momento ao usar seu chip da <xliff:g id="NETWORK_NAME">%1$s</xliff:g>.\n\nQuando a conexão for criptografada novamente, você vai receber outra notificação."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Configurações de segurança de rede móvel"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Saiba mais"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"Entendi"</string>
<string name="fcComplete" msgid="1080909484660507044">"Código de recurso concluído."</string>
<string name="fcError" msgid="5325116502080221346">"Problema de conexão ou código de recurso inválido."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -372,8 +360,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Fazer uma captura de tela"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Pode fazer uma captura de tela."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Visualização, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"dispensar"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"desativar ou modificar a barra de status"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Permite que o app desative a barra de status ou adicione e remova ícones do sistema."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"ser a barra de status"</string>
@@ -1224,7 +1211,7 @@
<string name="not_selected" msgid="410652016565864475">"não selecionado"</string>
<string name="rating_label" msgid="1837085249662154601">"{rating,plural, =1{1 de {max} estrelas}one{# de {max} estrelas}many{# de {max} estrelas}other{# de {max} estrelas}}"</string>
<string name="in_progress" msgid="2149208189184319441">"em andamento"</string>
- <string name="whichApplication" msgid="5432266899591255759">"Complete a ação usando"</string>
+ <string name="whichApplication" msgid="5432266899591255759">"Concluir a ação usando"</string>
<string name="whichApplicationNamed" msgid="6969946041713975681">"Concluir a ação usando %1$s"</string>
<string name="whichApplicationLabel" msgid="7852182961472531728">"Concluir ação"</string>
<string name="whichViewApplication" msgid="5733194231473132945">"Abrir com"</string>
@@ -2158,6 +2145,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Notificação de informação do modo rotina"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Economia de bateria ativada"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Reduzindo o uso da bateria para prolongar a duração dela"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"A Economia de bateria está ativada"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"A Economia de bateria está ativada para prolongar a duração da carga"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Economia de bateria"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"\"Economia de bateria\" desativada"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Não há carga suficiente no smartphone. Os recursos não estão mais restritos."</string>
@@ -2232,10 +2221,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Trocar para o app de trabalho?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Sua organização só permite fazer ligações usando apps de trabalho"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Sua organização só permite o envio de mensagens usando apps de trabalho"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"É possível fazer ligações apenas usando seu app Telefone pessoal. Essas ligações telefônicas serão adicionadas ao seu histórico pessoal."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"É possível enviar mensagens SMS apenas usando seu app Mensagens pessoal."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Usar o navegador pessoal"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Usar o navegador de trabalho"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Ligar"</string>
@@ -2415,8 +2402,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Trabalho 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Teste"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Público"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Perfil de trabalho"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Espaço privado"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Clone"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Público"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Conteúdo de notificação sensível oculto"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Conteúdo do app oculto no compartilhamento de tela por motivos de segurança"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Conectado automaticamente ao satélite"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index ac33fa1..10aa020 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -154,31 +154,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> după <xliff:g id="TIME_DELAY">{2}</xliff:g> secunde"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: neredirecționat"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: neredirecționat"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Securitatea rețelelor mobile"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Criptare, notificări pentru rețele necriptate"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"S-a accesat ID-ul dispozitivului"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"La <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, o rețea din apropiere a înregistrat ID-ul unic al dispozitivului tău (IMSI sau IMEI) în timp ce se folosea cardul tău SIM <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"La <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, o rețea din apropiere a înregistrat ID-ul unic al dispozitivului tău (IMSI sau IMEI) în timp ce se folosea cardul tău SIM <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>.\n\nAceasta înseamnă că locația, activitatea sau identitatea au fost înregistrate. Această practică este frecventă, dar poate fi o problemă pentru persoanele preocupate de confidențialitate."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Conectat la rețeaua criptată <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"Conexiunea la cardul SIM <xliff:g id="NETWORK_NAME">%1$s</xliff:g> este mai sigură acum"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Conectat la rețeaua necriptată"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Apelurile, mesajele și datele sunt acum mai vulnerabile în timp ce este folosit cardul SIM <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Apelurile, mesajele și datele sunt acum mai vulnerabile în timp ce este folosit cardul SIM <xliff:g id="NETWORK_NAME">%1$s</xliff:g>.\n\nCând conexiunea este din nou criptată, vei primi altă notificare."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Setări de securitate a rețelelor mobile"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Află mai multe"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"OK"</string>
<string name="fcComplete" msgid="1080909484660507044">"Cod de funcție complet."</string>
<string name="fcError" msgid="5325116502080221346">"Problemă de conectare sau cod de funcție nevalid."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -372,8 +360,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Fă o captură de ecran"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Poate face o captură de ecran."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Previzualizare, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"închide"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"dezactivare sau modificare bare de stare"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Permite aplicației să dezactiveze bara de stare sau să adauge și să elimine pictograme de sistem."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"să fie bara de stare"</string>
@@ -2158,6 +2145,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Notificare pentru informații despre modul Rutină"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Economisirea bateriei este activată"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Se reduce utilizarea bateriei pentru a-i extinde autonomia"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"Economisirea bateriei este activată"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"Economisirea bateriei este activată pentru a extinde autonomia"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Economisirea bateriei"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Economisirea bateriei a fost dezactivată"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Telefonul este încărcat suficient. Funcțiile nu mai sunt limitate."</string>
@@ -2232,10 +2221,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Comuți la aplicația pentru lucru?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Organizația îți permite să inițiezi apeluri numai din aplicațiile pentru lucru"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Organizația îți permite să trimiți mesaje numai din aplicațiile pentru lucru"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Poți să inițiezi apeluri telefonice numai din aplicația Telefon personală. Apelurile inițiate cu aplicația Telefon personală vor fi adăugate la istoricul apelurilor personale."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"Poți să trimiți mesaje SMS numai din aplicația personală pentru mesaje."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Folosește browserul personal"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Folosește browserul de serviciu"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Apelează"</string>
@@ -2415,8 +2402,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Serviciu 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Comun"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Profil de serviciu"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Spațiu privat"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Clonă"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Comun"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Conținutul sensibil din notificări a fost ascuns"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Conținutul aplicației este ascuns de permiterea accesului la ecran din motive de securitate"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"S-a conectat automat la satelit"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 63992d6..ff0d1b8 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -155,31 +155,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> через <xliff:g id="TIME_DELAY">{2}</xliff:g> с."</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Не переадресовано"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Не переадресовано"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Безопасность мобильной сети"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Шифрование, уведомления о незашифрованных сетях"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"Получен доступ к идентификатору устройства"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"В <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> при использовании SIM-карты (<xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>) в сети поблизости был записан уникальный идентификатор вашего устройства (IMSI или IMEI)."</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"В <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> при использовании SIM-карты (<xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>) в сети поблизости был записан уникальный идентификатор вашего устройства (IMSI или IMEI).\n\nВаше местоположение, действия или личность были зарегистрированы. Хотя в этом нет ничего необычного, раскрытие данных может доставлять проблемы людям, которые беспокоятся о своей конфиденциальности."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Подключение к зашифрованной сети \"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>\""</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"Теперь подключение SIM-карты (<xliff:g id="NETWORK_NAME">%1$s</xliff:g>) более безопасное."</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Подключение к незашифрованной сети"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Сейчас звонки, сообщения и данные более уязвимы при использовании SIM-карты (<xliff:g id="NETWORK_NAME">%1$s</xliff:g>)."</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Сейчас звонки, сообщения и данные более уязвимы при использовании SIM-карты (<xliff:g id="NETWORK_NAME">%1$s</xliff:g>).\n\nКогда соединение будет снова зашифровано, вы получите ещё одно уведомление."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Настройки безопасности мобильной сети"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Подробнее"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"ОК"</string>
<string name="fcComplete" msgid="1080909484660507044">"Код функции выполнен."</string>
<string name="fcError" msgid="5325116502080221346">"Неполадки подключения или неверный код функции."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"ОК"</string>
@@ -373,8 +361,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Создавать скриншоты"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Создавать снимки экрана."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"<xliff:g id="DREAM_NAME">%1$s</xliff:g>: предпросмотр"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"закрыть"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"Отключение/изменение строки состояния"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Приложение сможет отключать строку состояния, а также добавлять и удалять системные значки."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"Замена строки состояния"</string>
@@ -1911,7 +1898,7 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"Задача 2: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"Задача 3: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"Клонировать <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="private_profile_label_badge" msgid="1712086003787839183">"<xliff:g id="LABEL">%1$s</xliff:g> (личный профиль)"</string>
+ <string name="private_profile_label_badge" msgid="1712086003787839183">"<xliff:g id="LABEL">%1$s</xliff:g> (частный профиль)"</string>
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Запрашивать PIN-код"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Запрашивать графический ключ"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Запрашивать пароль"</string>
@@ -2012,7 +1999,7 @@
<string name="work_mode_emergency_call_button" msgid="6818855962881612322">"Экстренный вызов"</string>
<string name="set_up_screen_lock_title" msgid="8346083801616474030">"Настройте блокировку экрана"</string>
<string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Настроить блокировку экрана"</string>
- <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Чтобы использовать личное пространство, настройте блокировку экрана на этом устройстве."</string>
+ <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Чтобы использовать частное пространство, настройте блокировку экрана на этом устройстве."</string>
<string name="app_blocked_title" msgid="7353262160455028160">"Приложение недоступно"</string>
<string name="app_blocked_message" msgid="542972921087873023">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" сейчас недоступно."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"Недоступно: <xliff:g id="ACTIVITY">%1$s</xliff:g>"</string>
@@ -2159,6 +2146,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Уведомление о батарее"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Включен режим энергосбережения"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Экономия заряда продлит время работы от батареи."</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"Включен режим энергосбережения"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"Это нужно, чтобы продлить время работы от батареи."</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Режим энергосбережения"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Режим энергосбережения отключен"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Телефон заряжен достаточно. Функции больше не ограничены."</string>
@@ -2233,10 +2222,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Перейти в рабочее приложение?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"В вашей организации разрешено звонить только из рабочих приложений."</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"В вашей организации разрешено отправлять сообщения только из рабочих приложений."</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Вы можете звонить только из личного приложения \"Телефон\". Совершенные из него вызовы будут сохранены в личном журнале звонков."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"Вы можете отправлять SMS только из личного приложения \"Сообщения\"."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Использовать личный браузер"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Использовать рабочий браузер"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Позвонить"</string>
@@ -2416,8 +2403,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Рабочий 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Тестовый"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Совместный"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Рабочий профиль"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Частное пространство"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Клонированный"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Совместный"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Конфиденциальная информация в уведомлении скрыта"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Содержимое приложения исключено из демонстрации экрана в целях безопасности."</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Автоматически подключено к системам спутниковой связи"</string>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index 764b051..18b26f2 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: තත්පර <xliff:g id="TIME_DELAY">{2}</xliff:g> ට පසුව <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ඉදිරියට නොයවන ලදි"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ඉදිරියට නොයවන ලදි"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"ජංගම ජාල ආරක්ෂාව"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"සංකේතනය, සංකේතිත නොවන ජාල සඳහා දැනුම්දීම"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"උපාංග හැඳුනුමට ප්රවේශ වන ලදි"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"<xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> ට, අවට ජාලයක් ඔබේ <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> SIM පත භාවිත කළ විට ඔබේ උපාංගයේ අද්විතීය හැඳුනුම (IMSI හෝ IMEI) සටහන් කළේය."</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"<xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> ට, අවට ජාලයක් ඔබේ <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> SIM පත භාවිත කළ විට ඔබේ උපාංගයේ අද්විතීය හැඳුනුම (IMSI හෝ IMEI) සටහන් කළේය.\n\nඑනම් ඔබේ ස්ථානය, ක්රියාකාරකම, හෝ අනන්යතාව සටහන් කර ඇත. මෙය සාමාන්ය පුරුද්දකි, නමුත් පෞද්ගලිකත්වය ගැන සැලකිලිමත් වන පුද්ගලයින්ට ගැටලුවක් වේවි."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> සංකේතිත ජාලයට සම්බන්ධ කළා"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM සම්බන්ධතාව දැන් ඉතා සුරක්ෂිතයි"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"සංකේතිත නොවන ජාලයට සම්බන්ධ කළා"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"ඔබේ <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM පත භාවිත කරන අතරතුර ඇමතුම්, පණිවුඩ, සහ දත්ත දැනට ඉතා දුර්වලයි."</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"ඔබේ <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM පත භාවිත කරන අතරතුර ඇමතුම්, පණිවුඩ, සහ දත්ත දැනට ඉතා දුර්වලයි.\n\nඔබේ සම්බන්ධතාව නැවත සංකේතිත වූ විට, ඔබට තව දැනුම්දීමක් ලැබෙයි."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"ජංගම ජාල ආරක්ෂක සැකසීම්"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"තව දැන ගන්න"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"තේරුණා"</string>
<string name="fcComplete" msgid="1080909484660507044">"අංග කේතය සම්පූර්ණයි."</string>
<string name="fcError" msgid="5325116502080221346">"සම්බන්ධතා ගැටළුවක් හෝ අවලංගු විශේෂාංග කේතයකි."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"හරි"</string>
@@ -371,8 +359,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"තිර රුව ගන්න"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"සංදර්ශකයේ තිර රුවක් ගැනීමට හැකිය."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"පෙරදසුන, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"ඉවත ලන්න"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"තත්ව තීරුව අබල කරන්න හෝ වෙනස් කරන්න"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"තත්ව තීරුව අක්රිය කිරීමට හෝ පද්ධති නිරූපක එකතු හෝ ඉවත් කිරීමට යෙදුමට අවසර දේ."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"තත්ත්ව තීරුව බවට පත්වීම"</string>
@@ -2157,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"දිනචරියා ප්රකාර තතු දැනුම්දීම"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"බැටරි සුරැකුම ක්රියාත්මකයි"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"බැටරි ආයු කාලය දිගු කිරීම සඳහා බැටරි භාවිතය අඩු කිරීම"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"බැටරි සුරැකුම ක්රියාත්මකයි"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"බැටරි ආයු කාලය දීර්ඝ කිරීමට බැටරි සුරැකුම ක්රියාත්මක කර ඇත"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"බැටරි සුරැකුම"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"බැටරි සුරැකුම ක්රියාවිරහිත කර ඇත"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"දුරකථනයට ප්රමාණවත් ආරෝපණයක් තිබේ. විශේෂාංග තවදුරටත් සීමා කර නැත."</string>
@@ -2231,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"කාර්යාල යෙදුම වෙත මාරු වන්නද?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"ඔබේ සංවිධානය ඔබට කාර්යාල යෙදුම්වලින් ඇමතුම් කිරීමට පමණක් ඉඩ දෙයි"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"ඔබේ සංවිධානය ඔබට කාර්යාල යෙදුම්වලින් පණිවුඩ යැවීමට පමණක් ඉඩ දෙයි"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"ඔබට දුරකථන ඇමතුම් ගත හැක්කේ ඔබේ පුද්ගලික Phone යෙදුමින් පමණයි. පුද්ගලික Phone මගින් කරන ලද ඇමතුම් ඔබේ පුද්ගලික ඇමතුම් ඉතිහාසයට එක් කරනු ලැබේ."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"ඔබට කෙටි පණුවඩ යැවිය හැක්කේ ඔබේ පුද්ගලික Messages යෙදුමින් පමණයි."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"පුද්ගලික බ්රව්සරය භාවිත කරන්න"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"කාර්යාල බ්රව්සරය භාවිත කරන්න"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"අමතන්න"</string>
@@ -2414,6 +2401,10 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"කාර්යාලය 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"පරීක්ෂණය"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"වාර්ගික"</string>
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"කාර්යාල පැතිකඩ"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"රහසිගත අවකාශය"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"ක්ලෝන කරන්න"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"වාර්ගික"</string>
<string name="redacted_notification_message" msgid="1520587845842228816">"සංවේදී දැනුම්දීම් අන්තර්ගතය සැඟවී ඇත"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"ආරක්ෂාව සඳහා යෙදුම් අන්තර්ගතය තිරය බෙදා ගැනීමෙන් සඟවා ඇත"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 35b1760..3b144d2 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -155,31 +155,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> po <xliff:g id="TIME_DELAY">{2}</xliff:g> s"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nepresmerované"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nepresmerované"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Zabezpečenie mobilnej siete"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Šifrovanie, upozornenia na nešifrované siete"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"Bol zaznamenaný prístup k identifikátoru zariadenia"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"Sieť v okolí nahrala o <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> jedinečný identifikátor vášho zariadenia (IMSI alebo IMEI), keď ste používali SIM siete <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"Sieť v okolí nahrala o <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> jedinečný identifikátor vášho zariadenia (IMSI alebo IMEI), keď ste používali SIM siete <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>.\n\nZnamená to, že vaša poloha, aktivita alebo totožnosť bola zaznamenaná. Ide o bežný postup, ale môže to byť problém pre ľudí, ktorí majú obavy o ochranu súkromia."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Pripojené k šifrovanej sieti <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"Pripojenie SIM siete <xliff:g id="NETWORK_NAME">%1$s</xliff:g> je teraz zabezpečenejšie"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Pripojené k nešifrovanej sieti"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Hovory, správy a údaje sú momentálne zraniteľnejšie vzhľadom na nedostatok zabezpečenia pri používaní SIM siete <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Hovory, správy a údaje sú momentálne zraniteľnejšie vzhľadom na nedostatok zabezpečenia pri používaní SIM siete <xliff:g id="NETWORK_NAME">%1$s</xliff:g>.\n\nKeď bude vaše pripojenie znova šifrované, dostanete ďalšie upozornenie."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Nastavenia zabezpečenia mobilnej siete"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Ďalšie informácie"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"Dobre"</string>
<string name="fcComplete" msgid="1080909484660507044">"Požiadavka zadaná pomocou kódu funkcie bola úspešne dokončená."</string>
<string name="fcError" msgid="5325116502080221346">"Problém s pripojením alebo neplatný kód funkcie."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -373,8 +361,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Vytvoriť snímku obrazovky"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Je možné vytvoriť snímku obrazovky."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Ukážka, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"zavrieť"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"zakázanie alebo zmeny stavového riadka"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Umožňuje aplikácii vypnúť stavový riadok alebo pridať a odstrániť systémové ikony."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"vydávanie sa za stavový riadok"</string>
@@ -2159,6 +2146,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Upozornenie s informáciami o rutinnom režime"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Bol zapnutý šetrič batérie"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Zníženie spotreby batérie predlžuje jej výdrž"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"Šetrič batérie je zapnutý"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"Šetrič batérie ja zapnutý, aby sa predĺžila výdrž batérie"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Šetrič batérie"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Šetrič batérie bol vypnutý."</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Telefón je dostatočne nabitý. Funkcie už nie sú obmedzené."</string>
@@ -2233,10 +2222,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Chcete prepnúť na pracovnú aplikáciu?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Vaša organizácia vám povoľuje volať iba z pracovných aplikácií"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Vaša organizácia vám povoľuje posielať správy iba z pracovných aplikácií"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Volať môžete iba zo svojej osobnej telefónnej aplikácie. Hovory uskutočnené osobným telefónom budú pridané do vašej osobnej histórie hovorov."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"Správy SMS môžete posielať iba zo svojho osobného komunikátora."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Použiť osobný prehliadač"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Použiť pracovný prehliadač"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Volať"</string>
@@ -2416,6 +2403,10 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"3. pracovný"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Testovací"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Spoločný"</string>
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Pracovný profil"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Súkromný priestor"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Klon"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Spoločný"</string>
<string name="redacted_notification_message" msgid="1520587845842228816">"Obsah citlivého upozornenia je skrytý"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Obsah aplikácie bol na účely zabezpečenia skrytý v zdieľaní obrazovky"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index f80b5aa..1b7a2a1 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -155,31 +155,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> po toliko sekundah: <xliff:g id="TIME_DELAY">{2}</xliff:g>"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ni posredovano"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ni posredovano"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Varnost mobilnega omrežja"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Šifriranje, obvestila za nešifrirana omrežja"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"Dostop do ID-ja naprave"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"Ob <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> je omrežje v bližini zabeležilo enoznačni ID vaše naprave (IMSI ali IMEI) med uporabo kartice SIM omrežja <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"Ob <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> je omrežje v bližini zabeležilo enoznačni ID vaše naprave (IMSI ali IMEI) med uporabo kartice SIM omrežja <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>.\n\nTo pomeni, da je zabeležena vaša lokacija, dejavnost ali identiteta. To je običajna praksa, toda morda je to težava za ljudi, ki jih skrbi varnost."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Povezava s šifriranim omrežjem <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"Povezava kartice SIM omrežja <xliff:g id="NETWORK_NAME">%1$s</xliff:g> je zdaj varnejša"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Povezava z nešifriranim omrežjem"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Klici, sporočila in podatki so trenutno ranljivejši pri uporabi kartice SIM omrežja <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Klici, sporočila in podatki so trenutno ranljivejši pri uporabi kartice SIM omrežja <xliff:g id="NETWORK_NAME">%1$s</xliff:g>.\n\nKo bo povezava znova šifrirana, boste prejeli obvestilo."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Nastavitve varnosti mobilnega omrežja"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Več o tem"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"Razumem"</string>
<string name="fcComplete" msgid="1080909484660507044">"Koda funkcije je dokončana."</string>
<string name="fcError" msgid="5325116502080221346">"Težava s povezavo ali neveljavna koda funkcije."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"V redu"</string>
@@ -2158,6 +2146,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Rutinsko informativno obvestilo o načinu delovanja"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Varčevanje z energijo baterije je vklopljeno"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Manjša poraba energije baterije za podaljšanje časa delovanja baterije"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"Varčevanje z energijo baterije je vklopljeno"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"Varčevanje z energijo baterije je vklopljeno za podaljšanje časa delovanja pri baterijskem napajanju"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Varčevanje z energijo baterije"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Varčevanje z energijo baterije je izklopljeno"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Baterija v telefonu je dovolj napolnjena. Funkcije niso več omejene."</string>
@@ -2232,10 +2222,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Želite preklopiti na delovno aplikacijo?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Organizacija vam omogoča klicanje samo iz delovnih aplikacij."</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Organizacija vam omogoča pošiljanje sporočil samo iz delovnih aplikacij."</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Klicati je mogoče samo v osebni aplikaciji Telefon. Klici, opravljeni z osebno aplikacijo Telefon, se dodajo v osebno zgodovino klicev."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"Sporočila SMS je mogoče pošiljati samo v osebni aplikaciji Sporočila."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Uporabi osebni brskalnik"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Uporabi delovni brskalnik"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Pokliči"</string>
@@ -2415,6 +2403,10 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Delo 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Preizkus"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Skupno"</string>
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Delovni profil"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Zasebni prostor"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Klon"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Skupno"</string>
<string name="redacted_notification_message" msgid="1520587845842228816">"Občutljiva vsebina obvestila je bila skrita"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Pri deljenju zaslona je vsebina aplikacije skrita zaradi varnosti"</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 9f9907a4..142ab0d 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> pas <xliff:g id="TIME_DELAY">{2}</xliff:g> sekondash"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nuk u transferua"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nuk u transferua"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Siguria e rrjetit celular"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Enkriptimi, njoftimet për rrjetet e paenkriptuara"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"Pati qasje tek ID-ja e pajisjes"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"Në <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, një rrjet në afërsi ka regjistruar ID-në unike (IMSI ose IMEI) të pajisjes sate gjatë përdorimit të kartës sate SIM të <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"Në <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, një rrjet në afërsi ka regjistruar ID-në unike (IMSI ose IMEI) të pajisjes sate gjatë përdorimit të kartës sate SIM të <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>.\n\nKjo do të thotë që vendndodhja, aktiviteti ose identiteti yt janë regjistruar. Kjo është një praktikë të zakonshme, por mund të jetë problem për personat që janë të shqetësuar në lidhje me privatësinë."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Lidhur me rrjetin e enkriptuar <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"Lidhja e kartës SIM të <xliff:g id="NETWORK_NAME">%1$s</xliff:g> është më e sigurt tani"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Lidhur me një rrjet të paenkriptuar"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Telefonatat, mesazhet dhe të dhënat janë aktualisht më të cenueshme ndërkohë që përdoret karta jote SIM të <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Telefonatat, mesazhet dhe të dhënat janë aktualisht më të cenueshme ndërkohë që përdoret karta jote SIM të <xliff:g id="NETWORK_NAME">%1$s</xliff:g>.\n\nKur lidhja jote të jetë përsëri e enkriptuar, do të marrësh një njoftim tjetër."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Cilësimet e sigurisë së rrjetit celular"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Mëso më shumë"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"E kuptova"</string>
<string name="fcComplete" msgid="1080909484660507044">"Kodi i funksionit është i plotë."</string>
<string name="fcError" msgid="5325116502080221346">"Problem me lidhjen ose kod është i pavlefshëm."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"Në rregull"</string>
@@ -371,8 +359,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Nxirr një pamje të ekranit"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Mund të nxjerrë një pamje e ekranit."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Versioni paraprak, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"hiq"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"çaktivizo ose modifiko shiritin e statusit"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Lejon aplikacionin të çaktivizojë shiritin e statusit dhe të heqë ikonat e sistemit."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"të bëhet shiriti i statusit"</string>
@@ -2157,6 +2144,10 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Njoftimi i informacionit të \"Modalitetit rutinë\""</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"\"Kursyesi i baterisë\" u aktivizua"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Po reduktohet përdorimi i baterisë për të rritur kohëzgjatjen e baterisë"</string>
+ <!-- no translation found for dynamic_mode_notification_title_v2 (5072385242078021152) -->
+ <skip />
+ <!-- no translation found for dynamic_mode_notification_summary_v2 (2142444344663147938) -->
+ <skip />
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Kursyesi i baterisë"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"\"Kursyesi i baterisë\" është çaktivizuar"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Telefoni ka nivel të mjaftueshëm baterie. Funksionet nuk janë më të kufizuara."</string>
@@ -2231,10 +2222,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Të kalohet tek aplikacioni i punës?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Organizata jote të lejon që të telefonosh vetëm nga aplikacionet e punës"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Organizata jote të lejon që të dërgosh mesazhe vetëm nga aplikacionet e punës"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Mund të bësh telefonata vetëm nga aplikacioni personal \"Telefoni\". Telefonatat e bëra me aplikacionin personal \"Telefoni\" do të shtohen te historiku personal i telefonatave."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"Mund të dërgosh mesazhe SMS vetëm nga aplikacioni personal \"Mesazhet\"."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Përdor shfletuesin personal"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Përdor shfletuesin e punës"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Telefono"</string>
@@ -2414,8 +2403,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Puna 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"I përbashkët"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Profili i punës"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Hapësira private"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Klon"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"I përbashkët"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Përmbajtjet delikate të njoftimeve janë fshehur"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Përmbajtja e aplikacionit është fshehur nga ndarja e ekranit për arsye sigurie"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"U lidh automatikisht me satelitin"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index c67819a..87d1086 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -154,31 +154,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> након <xliff:g id="TIME_DELAY">{2}</xliff:g> секунде/и"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Није прослеђено"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Није прослеђено"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Безбедност на мобилној мрежи"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Шифровање, обавештења за нешифроване мреже"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"Приступљено је ИД-у уређаја"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"Мрежа у близини је у <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> евидентирала јединствени ИД вашег уређаја (IMSI или IMEI) док сте користили <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> SIM"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"Мрежа у близини је у <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> евидентирала јединствени ИД вашег уређаја (IMSI или IMEI) док сте користили <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> SIM.\n\nТо значи да је евидентирала вашу локацију, активност и идентитет. То је уобичајена пракса, али може да буде проблем људима који су забринути за приватност."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Повезани сте на шифровану мрежу <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"Веза <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM-а је сада безбеднија"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Повезани сте на шифровану мрежу"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Позиви, поруке и подаци су тренутно рањивији док користите <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Позиви, поруке и подаци су тренутно рањивији док користите <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM.\n\nКада веза поново буде шифрована, послаћемо вам друго обавештење."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Подешавања безбедности на мобилној мрежи"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Сазнајте више"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"Важи"</string>
<string name="fcComplete" msgid="1080909484660507044">"Кôд функције је извршен."</string>
<string name="fcError" msgid="5325116502080221346">"Проблеми са везом или неважећи кôд функције."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"Потврди"</string>
@@ -339,7 +327,7 @@
<string name="permgroupdesc_storage" msgid="5378659041354582769">"приступ фајловима на уређају"</string>
<string name="permgrouplab_readMediaAural" msgid="1858331312624942053">"Музика и звук"</string>
<string name="permgroupdesc_readMediaAural" msgid="7565467343667089595">"приступ музици и аудио садржају на уређају"</string>
- <string name="permgrouplab_readMediaVisual" msgid="4724874717811908660">"Слике и видео снимци"</string>
+ <string name="permgrouplab_readMediaVisual" msgid="4724874717811908660">"Слике и видеи"</string>
<string name="permgroupdesc_readMediaVisual" msgid="4080463241903508688">"приступ сликама и видеима на уређају"</string>
<string name="permgrouplab_microphone" msgid="2480597427667420076">"Микрофон"</string>
<string name="permgroupdesc_microphone" msgid="1047786732792487722">"снима звук"</string>
@@ -2157,6 +2145,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Обавештење о информацијама Рутинског режима"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Уштеда батерије је укључена"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Смањује се потрошња батерије да би се продужило њено трајање"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"Уштеда батерије је укључена"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"Уштеда батерије је укључена да би се продужило трајање батерије"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Уштеда батерије"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Уштеда батерије је искључена"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Батерија телефона је довољно напуњена. Функције више нису ограничене."</string>
@@ -2231,10 +2221,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Желите да пребаците на пословну апликацију?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Ваша организација дозвољава позивање само из пословних апликација"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Ваша организација дозвољава слање порука само из пословних апликација"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Телефонске позиве можете да упућујете само из личне апликације Телефон. Позиви упућени помоћу личне апликације Телефон додају се у личну историју позива."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"SMS поруке можете да шаљете само из личне апликације Messages."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Користи лични прегледач"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Користи пословни прегледач"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Позови"</string>
@@ -2414,8 +2402,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Посао 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Тест"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Заједничко"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Пословни профил"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Приватан простор"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Клонирано"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Заједничко"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Осетљив садржај обавештења је скривен"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Садржај апликације је скривен за дељење садржаја екрана због безбедности"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Аутоматски повезано са сателитом"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 01b30d2..3ca5c9f 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g><xliff:g id="DIALING_NUMBER">{1}</xliff:g> efter <xliff:g id="TIME_DELAY">{2}</xliff:g> sekunder"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>. Vidarebefordras inte"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Vidarebefordras inte"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Mobilnätverkssäkerhet"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Kryptering, aviseringar för okrypterade nätverk"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"Enhets-id har kommits åt"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"Kl. <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> loggade ett nätverk i närheten din enhets unika id (IMSI- eller IMEI-nummer) medan det använde ditt SIM-kort från <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"Kl. <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> loggade ett nätverk i närheten din enhets unika id (IMSI- eller IMEI-nummer) medan det använde ditt SIM-kort från <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>.\n\nDetta innebär att din plats, aktivitet eller identitet har loggats. Detta är allmän praxis, men kan vara ett problem för personer som är måna om sin integritet."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Ansluten till det krypterade nätverket <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"Anlutningen för SIM-kortet från <xliff:g id="NETWORK_NAME">%1$s</xliff:g> är säkrare nu"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Ansluten till okrypterat nätverk"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Samtal, meddelanden och data är i nuläget mer sårbara när du använder SIM-kortet från <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Samtal, meddelanden och data är i nuläget mer sårbara när du använder SIM-kortet från <xliff:g id="NETWORK_NAME">%1$s</xliff:g>.\n\nNär din anslutning krypteras igen får du en till avisering."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Inställningar för mobilnätverkssäkerhet"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Läs mer"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"OK"</string>
<string name="fcComplete" msgid="1080909484660507044">"Funktionskoden är fullständig."</string>
<string name="fcError" msgid="5325116502080221346">"Anslutningsproblem eller ogiltig funktionskod."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -371,8 +359,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ta skärmbild"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Kan ta en skärmbild av skärmen."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Förhandsgranskar <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"stäng"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"inaktivera eller ändra statusfält"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Tillåter att appen inaktiverar statusfältet eller lägger till och tar bort systemikoner."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"visas i statusfältet"</string>
@@ -2157,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Avisering om rutinläge"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Batterisparläget har aktiverats"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Minskar batteriförbrukning för att förlänga batteritiden"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"Batterisparläget är aktiverat"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"Batterisparläget är aktiverat för att förlänga batteritiden"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Batterisparläge"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Batterisparläget har inaktiverats"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Telefonen har laddats tillräckligt. Funktioner begränsas inte längre."</string>
@@ -2231,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Vill du byta till jobbappen?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Organisationen tillåter endast att du ringer samtal med jobbappar"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Organisationen tillåter endast att du skickar meddelanden med jobbappar"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Du kan bara ringa telefonsamtal från din personliga app Telefon. Samtal som görs med din personliga Telefon läggs till i din personliga samtalshistorik."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"Du kan bara skicka sms från din personliga Messages-app."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Använd privat webbläsare"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Använd jobbwebbläsare"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Ring"</string>
@@ -2414,8 +2401,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Arbete 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Allmän"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Jobbprofil"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Privat område"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Klona"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Allmän"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Känsligt aviseringsinnehåll dolt"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Av säkerhetsskäl döljs appinnehållet vid skärmdelning"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Automatiskt ansluten till satellit"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index df30800..2efca2b 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> baada ya sekunde <xliff:g id="TIME_DELAY">{2}</xliff:g>"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Haijasambazwa"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Haijatumiwa mwingine"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Usalama wa mtandao wa simu"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Usimbaji fiche, arifa za mitandao ambayo haijasimbwa kwa njia fiche"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"Kitambulisho cha kifaa kimefikiwa"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"Saa <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, mtandao wa karibu nawe ulirekodi kitambulisho cha kipekee cha kifaa chako (IMSI au IMEI) ulipokuwa ukitumia SIM yako ya <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"Saa <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, mtandao wa karibu nawe ulirekodi kitambulisho cha kipekee cha kifaa chako (IMSI au IMEI) ulipokuwa ukitumia SIM yako ya <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>.\n\nHii inamaanisha kuwa data ya mahali ulipo, shughuli au utambulisho wako imewekwa kwenye kumbukumbu. Hii ni desturi ya kawaida, lakini inaweza kuwa tatizo kwa watu wanaozingatia masuala ya faragha kwa undani."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Imeunganishwa kwenye mtandao uliosimbwa kwa njia fiche wa <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"Sasa muunganisho wa SIM wa <xliff:g id="NETWORK_NAME">%1$s</xliff:g> ni salama zaidi"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Imeunganishwa kwenye mtandao ambao haujasimbwa kwa njia fiche"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Kwa sasa maudhui ya simu, ujumbe na data yako katika hatari ya kuvamiwa unapotumia SIM yako ya <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Kwa sasa maudhui ya simu, ujumbe na data yako katika hatari ya kuvamiwa unapotumia SIM yako ya <xliff:g id="NETWORK_NAME">%1$s</xliff:g>.\n\nMuunganisho wako ukisimbwa kwa njia fiche tena, utapata arifa nyingine."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Mipangilio ya usalama wa mtandao wa simu"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Pata maelezo zaidi"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"Nimeelewa"</string>
<string name="fcComplete" msgid="1080909484660507044">"Msimbo wa kipengele umekamilika."</string>
<string name="fcError" msgid="5325116502080221346">"Tatizo la muunganisho au msimbo batili wa kipengele."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"Sawa"</string>
@@ -2156,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Arifa ya maelezo ya Hali ya Kawaida"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Kiokoa Betri kimewashwa"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Inapunguza matumizi ya betri ili kuongeza muda wa matumizi ya betri"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"Kiokoa Betri kimewashwa"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"Kiokoa Betri kimewashwa ili kuongeza muda wa matumizi ya betri"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Kiokoa betri"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Kiokoa Betri kimezimwa"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Simu ina chaji ya kutosha. Vipengele havizuiliwi tena."</string>
@@ -2230,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Ungependa kutumia programu ya kazini?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Shirika lako linakuruhusu upige simu ukitumia programu za kazini pekee"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Shirika lako linakuruhusu utume ujumbe ukitumia programu za kazini pekee"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Unaweza kupiga simu pekee kwa kutumia programu yako binafsi ya Simu. Simu unazopiga kwa kutumia programu binafsi ya Simu zitawekwa kwenye rekodi yako binafsi ya simu zilizopigwa."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"Unaweza kutuma ujumbe wa SMS pekee kwa kutumia programu yako binafsi ya Messages."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Tumia kivinjari cha binafsi"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Tumia kivinjari cha kazini"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Piga simu"</string>
@@ -2413,8 +2401,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Wa 3 wa Kazini"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Jaribio"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Unaoshirikiwa"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Wasifu wa kazini"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Sehemu ya faragha"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Nakala"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Wasifu wa pamoja"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Maudhui nyeti kwenye arifa yamefichwa"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Maudhui ya programu yamefichwa ili yasionekane kwenye skrini ya pamoja kwa sababu za kiusalama"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Imeunganishwa kiotomatiki na satelaiti"</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 69b3f9b..0c704e3 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="TIME_DELAY">{2}</xliff:g> வினாடிகளுக்குப் பிறகு <xliff:g id="DIALING_NUMBER">{1}</xliff:g> ஐப் பகிர்"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: பகிரப்படவில்லை"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: பகிரப்படவில்லை"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"மொபைல் நெட்வொர்க் பாதுகாப்பு"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"என்க்ரிப்ஷன், என்க்ரிப்ஷன் செய்யப்படாத நெட்வொர்க்குகளுக்கான அறிவிப்புகள்"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"சாதன ஐடி அணுகப்பட்டது"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"<xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>க்கு, உங்கள் <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> சிம்மைப் பயன்படுத்தும்போது அருகிலுள்ள நெட்வொர்க் உங்கள் சாதனத்தின் தனிப்பட்ட ஐடியை (IMSI அல்லது IMEI) ரெக்கார்டு செய்துள்ளது"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"<xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>க்கு, உங்கள் <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> சிம்மைப் பயன்படுத்தும்போது அருகிலுள்ள நெட்வொர்க் உங்கள் சாதனத்தின் தனிப்பட்ட ஐடியை (IMSI அல்லது IMEI) ரெக்கார்டு செய்துள்ளது.\n\nஅதாவது உங்கள் இருப்பிடம், செயல்பாடு அல்லது அடையாளம் பதிவுசெய்யப்பட்டுள்ளது. இது பொதுவான நடைமுறையாகும். ஆனால் தனியுரிமை பற்றிய அக்கறை கொண்டவர்களுக்கு இது ஒரு பிரச்சனையாக இருக்கலாம்."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"என்க்ரிப்ஷன் செய்யப்பட்ட நெட்வொர்க் <xliff:g id="NETWORK_NAME">%1$s</xliff:g> உடன் இணைக்கப்பட்டுள்ளது"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> சிம் இணைப்பு இப்போது மிகவும் பாதுகாப்பானது"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"என்க்ரிப்ஷன் செய்யப்படாத நெட்வொர்க்குடன் இணைக்கப்பட்டுள்ளது"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"உங்கள் <xliff:g id="NETWORK_NAME">%1$s</xliff:g> சிம்மைப் பயன்படுத்தும்போது அழைப்புகள், மெசேஜ்கள், தரவு ஆகியவை தற்போது மிக எளிதாகப் பாதிப்புக்குள்ளாகலாம்"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"உங்கள் <xliff:g id="NETWORK_NAME">%1$s</xliff:g> சிம்மைப் பயன்படுத்தும்போது அழைப்புகள், மெசேஜ்கள், தரவு ஆகியவை தற்போது மிக எளிதாகப் பாதிப்புக்குள்ளாகலாம்.\n\nஉங்கள் இணைப்பு மீண்டும் என்க்ரிப்ஷன் செய்யப்பட்டவுடன், மற்றொரு அறிவிப்பைப் பெறுவீர்கள்."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"மொபைல் நெட்வொர்க் பாதுகாப்பு அமைப்புகள்"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"மேலும் அறிக"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"சரி"</string>
<string name="fcComplete" msgid="1080909484660507044">"பிரத்தியேக குறியீடு முடிந்தது."</string>
<string name="fcError" msgid="5325116502080221346">"இணைப்பு சிக்கல் அல்லது தவறான அம்சக் குறியீடு."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"சரி"</string>
@@ -371,8 +359,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ஸ்கிரீன்ஷாட்டை எடுக்கும்"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"டிஸ்ப்ளேவை ஸ்கிரீன்ஷாட் எடுக்க முடியும்."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"மாதிரிக்காட்சி, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"மூடுக"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"நிலைப் பட்டியை முடக்குதல் அல்லது மாற்றுதல்"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"நிலைப் பட்டியை முடக்க அல்லது முறைமையில் ஐகான்களைச் சேர்க்க மற்றும் அகற்ற ஆப்ஸை அனுமதிக்கிறது."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"நிலைப் பட்டியில் இருக்கும்"</string>
@@ -2157,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"வழக்கமான பேட்டரி சேமிப்பானுக்கான விவர அறிவிப்பு"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"பேட்டரி சேமிப்பு இயக்கப்பட்டுள்ளது"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"பேட்டரி ஆயுளை நீட்டிக்க, பேட்டரி உபயோகத்தைக் குறைக்கிறது"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"பேட்டரி சேமிப்பான் இயக்கத்தில் உள்ளது"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"பேட்டரி ஆயுளை நீட்டிக்க பேட்டரி சேமிப்பான் இயக்கப்பட்டது"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"பேட்டரி சேமிப்பு"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"பேட்டரி சேமிப்பான் ஆஃப் செய்யப்பட்டுள்ளது"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"மொபைலில் போதுமான சார்ஜ் உள்ளது. அம்சங்கள் இனி தடையின்றி இயங்கும்."</string>
@@ -2231,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"பணி ஆப்ஸுக்கு மாற வேண்டுமா?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"உங்கள் நிறுவனம் பணி ஆப்ஸில் இருந்து மட்டுமே அழைக்க உங்களை அனுமதிக்கிறது"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"உங்கள் நிறுவனம் பணி ஆப்ஸில் இருந்து மட்டுமே மெசேஜ்களை அனுப்ப உங்களை அனுமதிக்கிறது"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"உங்கள் தனிப்பட்ட ஃபோன் ஆப்ஸில் இருந்து மட்டுமே நீங்கள் மொபைல் அழைப்புகளைச் செய்ய முடியும். தனிப்பட்ட ஃபோன் ஆப்ஸ் மூலம் செய்யப்படும் அழைப்புகள் உங்கள் தனிப்பட்ட அழைப்புப் பதிவில் சேர்க்கப்படும்."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"உங்கள் தனிப்பட்ட Messages ஆப்ஸில் இருந்து மட்டுமே நீங்கள் SMS மெசேஜ்களை அனுப்ப முடியும்."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"தனிப்பட்ட உலாவியைப் பயன்படுத்து"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"பணி உலாவியைப் பயன்படுத்து"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"அழை"</string>
@@ -2414,8 +2401,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"பணி 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"பரிசோதனை"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"பொது"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"பணிக் கணக்கு"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"ரகசிய இடம்"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"குளோன்"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"பொது"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"உணர்வுபூர்வமான அறிவிப்பு உள்ளடக்கம் மறைக்கப்பட்டது"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"பாதுகாப்பிற்காக, திரைப் பகிர்வில் இருந்து ஆப்ஸ் உள்ளடக்கம் மறைக்கப்பட்டுள்ளது"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"சாட்டிலைட்டுடன் தானாக இணைக்கப்பட்டது"</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index b6c6086..b465000 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="TIME_DELAY">{2}</xliff:g> సెకన్ల తర్వాత <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ఫార్వర్డ్ చేయబడలేదు"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ఫార్వర్డ్ చేయబడలేదు"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"మొబైల్ నెట్వర్క్ సెక్యూరిటీ"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"ఎన్క్రిప్షన్, ఎన్క్రిప్ట్ చేయని నెట్వర్క్లకు సంబంధించిన నోటిఫికేషన్లు"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"పరికర IDని యాక్సెస్ చేశారు"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"మీ <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> SIMను ఉపయోగిస్తున్నప్పుడు, సమీపంలోని నెట్వర్క్ <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> సమయానికి మీ పరికర యూనిక్ ID (IMSI లేదా IMEI)ని రికార్డ్ చేసింది"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"మీ <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> SIMను ఉపయోగిస్తున్నప్పుడు, సమీపంలోని నెట్వర్క్ <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> సమయానికి మీ పరికర యూనిక్ ID (IMSI లేదా IMEI)ని రికార్డ్ చేసింది.\n\nమీ లొకేషన్, యాక్టివిటీ, లేదా గుర్తింపు లాగ్ అయ్యాయని దీని అర్థం. దీనిని తరచుగా అమలు చేస్తుంటారు, కానీ గోప్యత గురించి ఆందోళనపడే వ్యక్తులకు ఇది సమస్య కావచ్చు,"</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"ఎన్క్రిప్ట్ చేసిన నెట్వర్క్ <xliff:g id="NETWORK_NAME">%1$s</xliff:g>కు కనెక్ట్ అయింది"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM కనెక్షన్ ఇప్పుడు మరింత సురక్షితంగా ఉంది"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"ఎన్క్రిప్ట్ చేయని నెట్వర్క్కు కనెక్ట్ అయింది"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"మీరు ప్రస్తుతం <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIMను ఉపయోగిస్తున్నప్పుడు కాల్స్, మెసేజ్లు, డేటా చోరీకి గురయ్యే అవకాశం ఎక్కువ"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"మీరు <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIMను ఉపయోగిస్తున్నప్పుడు, ప్రస్తుతం కాల్స్, మెసేజ్లు, డేటా చోరీకి గురయ్యే అవకాశం ఎక్కువ.\n\nమీ కనెక్షన్ను మళ్లీ ఎన్క్రిప్ట్ చేసినప్పుడు, మీకు మరొక నోటిఫికేషన్ అందుతుంది."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"మొబైల్ నెట్వర్క్ సెక్యూరిటీ సెట్టింగ్లు"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"మరింత తెలుసుకోండి"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"అర్థమైంది"</string>
<string name="fcComplete" msgid="1080909484660507044">"లక్షణం కోడ్ పూర్తయింది."</string>
<string name="fcError" msgid="5325116502080221346">"కనెక్షన్ సమస్య లేదా లక్షణం కోడ్ చెల్లదు."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"సరే"</string>
@@ -1223,7 +1211,7 @@
<string name="rating_label" msgid="1837085249662154601">"{rating,plural, =1{{max}కి ఒక స్టార్}other{{max}కి # స్టార్లు}}"</string>
<string name="in_progress" msgid="2149208189184319441">"ప్రోగ్రెస్లో ఉంది"</string>
<string name="whichApplication" msgid="5432266899591255759">"దీన్ని ఉపయోగించి చర్యను పూర్తి చేయండి"</string>
- <string name="whichApplicationNamed" msgid="6969946041713975681">"%1$sను ఉపయోగించి చర్యను పూర్తి చేయి"</string>
+ <string name="whichApplicationNamed" msgid="6969946041713975681">"%1$sను ఉపయోగించి చర్యను పూర్తి చేయండి"</string>
<string name="whichApplicationLabel" msgid="7852182961472531728">"చర్యను పూర్తి చేయి"</string>
<string name="whichViewApplication" msgid="5733194231473132945">"దీనితో తెరువు"</string>
<string name="whichViewApplicationNamed" msgid="415164730629690105">"%1$sతో తెరువు"</string>
@@ -2156,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"రొటీన్ మోడ్ సమాచార నోటిఫికేషన్"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"బ్యాటరీ సేవర్ ఆన్ చేయబడింది"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"బ్యాటరీ జీవితకాలాన్ని పొడిగించడానికి బ్యాటరీ వినియోగాన్ని తగ్గించడం"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"బ్యాటరీ సేవర్ ఆన్లో ఉంది"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"బ్యాటరీ లైఫ్ను పొడిగించడానికి బ్యాటరీ సేవర్ ఆన్ చేయబడింది"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"బ్యాటరీ సేవర్"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"బ్యాటరీ సేవర్ ఆఫ్ చేయబడింది"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"ఫోన్కు తగినంత ఛార్జింగ్ ఉంది. ఫీచర్లు ఇప్పటి నుండి పరిమితం చేయబడవు."</string>
@@ -2230,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"వర్క్ యాప్నకు మారాలా?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"మీ సంస్థ, వర్క్ యాప్ల నుండి మాత్రమే కాల్స్ చేయడానికి మిమ్మల్ని అనుమతిస్తుంది"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"మీ సంస్థ, వర్క్ యాప్ల నుండి మాత్రమే మెసేజ్లను పంపడానికి మిమ్మల్ని అనుమతిస్తుంది"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"మీ వ్యక్తిగత ఫొన్ యాప్ నుండి మీరు ఫోన్ కాల్స్ మాత్రమే చేయగలరు. వ్యక్తిగత ఫోన్తో చేసిన కాల్స్ మీ వ్యక్తిగత కాల్ హిస్టరీకి జోడించబడతాయి."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"మీ వ్యక్తిగత Messages యాప్ నుండి మీరు SMS మెసేజ్లను పంపగలరు."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"వ్యక్తిగత బ్రౌజర్ను ఉపయోగించండి"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"వర్క్ బ్రౌజర్ను ఉపయోగించండి"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"కాల్ చేయండి"</string>
@@ -2413,6 +2401,10 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"ఆఫీస్ 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"పరీక్ష"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"కమ్యూనల్"</string>
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"వర్క్ ప్రొఫైల్"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"ప్రైవేట్ స్పేస్"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"క్లోన్"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"కమ్యూనల్"</string>
<string name="redacted_notification_message" msgid="1520587845842228816">"గోప్యమైన నోటిఫికేషన్ కంటెంట్ దాచబడింది"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"సెక్యూరిటీ కోసం స్క్రీన్ షేర్ నుండి యాప్ కంటెంట్ దాచబడింది"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index c9a2027..535396d 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> หลังผ่านไป <xliff:g id="TIME_DELAY">{2}</xliff:g> วินาที"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ไม่ได้โอนสาย"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ไม่ได้โอนสาย"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"การรักษาความปลอดภัยของเครือข่ายมือถือ"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"การเข้ารหัส การแจ้งเตือนสำหรับเครือข่ายที่ไม่ได้เข้ารหัส"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"เข้าถึงรหัสอุปกรณ์แล้ว"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"เมื่อเวลา <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> เครือข่ายใกล้เคียงได้บันทึกรหัสที่ไม่ซ้ำกัน (IMSI หรือ IMEI) ของอุปกรณ์ของคุณในขณะที่ใช้ซิม <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"เมื่อเวลา <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> เครือข่ายใกล้เคียงได้บันทึกรหัสที่ไม่ซ้ำกัน (IMSI หรือ IMEI) ของอุปกรณ์ของคุณในขณะที่ใช้ซิม <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>\n\nนั่นหมายความว่ามีการบันทึกตำแหน่ง กิจกรรม หรือข้อมูลประจำตัวของคุณ การดำเนินการนี้เป็นแนวทางปฏิบัติทั่วไปแต่อาจเป็นปัญหาสำหรับผู้ที่มีความกังวลในเรื่องความเป็นส่วนตัว"</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"เชื่อมต่อกับเครือข่าย <xliff:g id="NETWORK_NAME">%1$s</xliff:g> ที่เข้ารหัสแล้ว"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"การเชื่อมต่อซิม <xliff:g id="NETWORK_NAME">%1$s</xliff:g> มีความปลอดภัยมากขึ้นแล้ว"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"เชื่อมต่อกับเครือข่ายที่ไม่ได้เข้ารหัสแล้ว"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"ตอนนี้การโทร ข้อความ และข้อมูลมีความเสี่ยงมากขึ้นในขณะที่ใช้ซิม <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"ตอนนี้การโทร ข้อความ และข้อมูลมีความเสี่ยงมากขึ้นในขณะที่ใช้ซิม <xliff:g id="NETWORK_NAME">%1$s</xliff:g>\n\nเมื่อมีการเข้ารหัสการเชื่อมต่ออีกครั้ง คุณจะได้รับการแจ้งเตือนอีกครั้งหนึ่ง"</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"การตั้งค่าการรักษาความปลอดภัยของเครือข่ายมือถือ"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"ดูข้อมูลเพิ่มเติม"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"รับทราบ"</string>
<string name="fcComplete" msgid="1080909484660507044">"รหัสฟีเจอร์เสร็จสมบูรณ์"</string>
<string name="fcError" msgid="5325116502080221346">"พบปัญหาในการเชื่อมต่อหรือรหัสฟีเจอร์ไม่ถูกต้อง"</string>
<string name="httpErrorOk" msgid="6206751415788256357">"ตกลง"</string>
@@ -2156,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"การแจ้งเตือนข้อมูลโหมดกิจวัตร"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"เปิดโหมดประหยัดแบตเตอรี่แล้ว"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"ลดการใช้งานแบตเตอรี่เพื่อยืดอายุการใช้งานแบตเตอรี่"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"โหมดประหยัดแบตเตอรี่เปิดอยู่"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"เปิดโหมดประหยัดแบตเตอรี่แล้วเพื่อยืดระยะเวลาการใช้งานแบตเตอรี่"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"โหมดประหยัดแบตเตอรี่"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"ปิดโหมดประหยัดแบตเตอรี่แล้ว"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"โทรศัพท์มีแบตเตอรี่เพียงพอ ไม่มีการจำกัดฟีเจอร์แล้ว"</string>
@@ -2230,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"เปลี่ยนไปใช้แอปงานไหม"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"องค์กรอนุญาตให้คุณโทรออกได้จากแอปงานเท่านั้น"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"องค์กรอนุญาตให้คุณส่งข้อความได้จากแอปงานเท่านั้น"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"คุณจะโทรออกได้จากแอปโทรศัพท์ส่วนตัวเท่านั้น โดยระบบจะเพิ่มการโทรที่ดำเนินการด้วยแอปดังกล่าวลงในประวัติการโทรส่วนตัวของคุณ"</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"คุณจะส่งข้อความ SMS ได้จากแอปข้อความส่วนตัวเท่านั้น"</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"ใช้เบราว์เซอร์ส่วนตัว"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"ใช้เบราว์เซอร์งาน"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"โทร"</string>
@@ -2413,8 +2401,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"งาน 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"ทดสอบ"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"ส่วนกลาง"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"โปรไฟล์งาน"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"พื้นที่ส่วนตัว"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"โคลน"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"ส่วนกลาง"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"เนื้อหาการแจ้งเตือนที่ละเอียดอ่อนซ่อนอยู่"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"ซ่อนเนื้อหาแอปจากการแชร์หน้าจอเพื่อความปลอดภัย"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"เชื่อมต่อกับดาวเทียมโดยอัตโนมัติ"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 4428dc8..6eab396 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> pagkatapos ng <xliff:g id="TIME_DELAY">{2}</xliff:g> (na) segundo"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Hindi naipasa"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Hindi ipinasa"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Seguridad ng mobile network"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Pag-encrypt, mga notification para sa mga hindi naka-encrypt na network"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"Na-access ang Device ID"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"Nang <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, na-record ng isang kalapit na network ang natatanging ID ng iyong device (IMSI o IMEI) habang ginagamit ang iyong <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> SIM"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"Nang <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, na-record ng isang kalapit na network ang natatanging ID ng iyong device (IMSI o IMEI) habang ginagamit ang iyong <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> SIM.\n\nIbig sabihin, na-log ang iyong lokasyon, aktibidad, o pagkakakilanlan. Isa itong karaniwang kagawian pero posibleng isang isyu para sa mga taong nag-aalala tungkol sa privacy."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Nakakonekta sa naka-encrypt na network na <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"Mas secure na ang koneksyon ng <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Nakakonekta sa hindi naka-encrypt na network"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Kasalukuyang mas nanganganib ang mga tawag, mensahe, at data habang ginagamit ang iyong <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Kasalukuyang mas nanganganib ang mga tawag, mensahe, at data habang ginagamit ang iyong <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM.\n\nKapag na-encrypt ulit ang iyong koneksyon, makakatanggap ka ng isa pang notification."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Mga setting ng seguridad ng mobile network"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Matuto pa"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"OK"</string>
<string name="fcComplete" msgid="1080909484660507044">"Kumpleto na ang code ng tampok."</string>
<string name="fcError" msgid="5325116502080221346">"Problema sa koneksyon o di-wastong code ng tampok."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -371,8 +359,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Kumuha ng screenshot"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Puwedeng kumuha ng screenshot ng display."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Preview, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"i-dismiss"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"i-disable o baguhin ang status bar"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Pinapayagan ang app na i-disable ang status bar o magdagdag at mag-alis ng mga icon ng system."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"maging status bar"</string>
@@ -2157,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Notification ng impormasyon ng Routine Mode"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Na-on ang Pantipid ng Baterya"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Binabawasan ang paggamit sa baterya para mapatagal ang baterya"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"Naka-on ang Pantipid ng Baterya"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"Naka-on ang Pantipid ng Baterya para mapahaba ang tagal ng baterya"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Pantipid ng Baterya"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Na-off ang Pantipid ng Baterya"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"May sapat na charge ang telepono. Hindi na pinaghihigpitan ang mga feature."</string>
@@ -2231,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Lumipat sa app para sa trabaho?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Pinapayagan ka lang ng iyong organisasyon na tumawag mula sa mga app para sa trabaho"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Pinapayagan ka lang ng iyong organisasyon na magpadala ng mga mensahe mula sa mga app para sa trabaho"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Puwede ka lang tumawag sa telepono mula sa iyong personal na App na Telepono. Idaragdag sa iyong personal na history ng tawag ang mga tawag na ginawa gamit ang personal na Telepono mo."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"Puwede ka lang magpadala ng mga mensaheng SMS mula sa iyong personal na Messages app."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Gamitin ang personal na browser"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Gamitin ang browser sa trabaho"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Tumawag"</string>
@@ -2414,8 +2401,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Trabaho 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Communal"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Profile sa trabaho"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Pribadong space"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Clone"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Communal"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Nakatago ang content ng sensitibong notification"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Nakatago ang content ng app mula sa pagbabahagi ng screen para sa seguridad"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Awtomatikong nakakonekta sa satellite"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 3d022a8..4c8083a 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="TIME_DELAY">{2}</xliff:g> saniye sonra <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Yönlendirilmedi"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Yönlendirilmedi"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Mobil ağ güvenliği"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Şifreleme, şifrelenmemiş ağlarla ilgili bildirimler"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"Cihaz kimliğine erişildi"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"Yakındaki bir ağ, <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> sularında <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> SIM\'inizi kullanırken cihazınızın benzersiz kimliğini (IMSI veya IMEI) kaydetti"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"Yakındaki bir ağ, <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> sularında <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> SIM\'inizi kullanırken cihazınızın benzersiz kimliğini (IMSI veya IMEI) kaydetti.\n\nDolayısıyla konumunuz, etkinliğiniz veya kimliğiniz günlüğe kaydedildi. Bu yaygın bir uygulama olsa da gizlilik konusunda endişe duyan kişiler açısından sorun olabilir."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Şifrelenmiş <xliff:g id="NETWORK_NAME">%1$s</xliff:g> ağına bağlanıldı"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM bağlantısı artık daha güvenli"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Şifrelenmemiş ağa bağlanıldı"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Aramalar, mesajlar ve veriler şu anda <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM\'inizi kullanırken daha savunmasız durumda"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Aramalar, mesajlar ve veriler şu anda <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM\'inizi kullanırken daha savunmasız durumda.\n\nBağlantınız tekrar şifrelendiğinde başka bir bildirim alacaksınız."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Mobil ağ güvenliği ayarları"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Daha fazla bilgi"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"Anladım"</string>
<string name="fcComplete" msgid="1080909484660507044">"Özellik kodu tamamlandı."</string>
<string name="fcError" msgid="5325116502080221346">"Bağlantı sorunu veya geçersiz özellik kodu."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"Tamam"</string>
@@ -371,8 +359,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ekran görüntüsü al"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Ekran görüntüsü alınabilir."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Önizleme, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"kapat"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"durum çubuğunu devre dışı bırak veya değiştir"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Uygulamaya, durum çubuğunu devre dışı bırakma ve sistem simgelerini ekleyip kaldırma izni verir."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"durum çubuğunda olma"</string>
@@ -2157,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Rutin Modu bilgi bildirimi"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Pil Tasarrufu açıldı"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Pil ömrünü uzatmak için pil kullanımını azaltma"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"Pil Tasarrufu açık"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"Pil ömrünü uzatmak için Pil Tasarrufu özelliği açıldı"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Pil Tasarrufu"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Pil Tasarrufu kapatıldı"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Telefon yeterince şarj oldu. Özellikler artık kısıtlanmış değil."</string>
@@ -2231,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"İş uygulamasına geçilsin mi?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Kuruluşunuz yalnızca iş uygulamalarından telefon etmenize izin veriyor"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Kuruluşunuz yalnızca iş uygulamalarından mesaj göndermenize izin veriyor"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Yalnızca kişisel Telefon uygulamanızdan telefon edebilirsiniz. Kişisel Telefon uygulamasıyla yapılan aramalar, kişisel çağrı geçmişinize eklenir."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"Yalnızca kişisel Mesajlar uygulamanızdan SMS gönderebilirsiniz."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Kişisel tarayıcıyı kullan"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"İş tarayıcısını kullan"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Telefon et"</string>
@@ -2414,8 +2401,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"İş 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Paylaşılan"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"İş profili"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Özel alan"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Klon"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Paylaşılan"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Hassas bildirim içerikleri gizlendi"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Uygulama içerikleri, güvenlik nedeniyle ekran paylaşımında gizlendi"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Uyduya otomatik olarak bağlandı"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index e272f5f..6f94a2c 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -155,31 +155,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> після <xliff:g id="TIME_DELAY">{2}</xliff:g> сек."</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: не переслано"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: не переслано"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Безпека мобільної мережі"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Шифрування, сповіщення для незашифрованих мереж"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"Отримано доступ до ідентифікатора пристрою"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"О <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> у мережі поблизу зафіксовано унікальний ідентифікатор вашого пристрою (IMSI або IMEI) під час використання вашої SIM-карти <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"О <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> у мережі поблизу зафіксовано унікальний ідентифікатор вашого пристрою (IMSI або IMEI) під час використання вашої SIM-карти <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>.\n\nЦе означає, що було зареєстровано ваше місцезнаходження, дії чи особу. Це звичайна практика, але може виявитися проблемою для людей, для яких важлива конфіденційність."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Підключено до зашифрованої мережі <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"Тепер з’єднання SIM-карти <xliff:g id="NETWORK_NAME">%1$s</xliff:g> краще захищене"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Підключено до незашифрованої мережі"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Зараз під час використання SIM-карти <xliff:g id="NETWORK_NAME">%1$s</xliff:g> дзвінки, повідомлення й дані більш вразливі"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Зараз під час використання SIM-карти <xliff:g id="NETWORK_NAME">%1$s</xliff:g> дзвінки, повідомлення й дані більш вразливі.\n\nКоли ви знову підключитеся до зашифрованої мережі, ви отримаєте ще одне сповіщення."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Налаштування безпеки мобільної мережі"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Докладніше"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"OK"</string>
<string name="fcComplete" msgid="1080909484660507044">"Сервісний код виконано."</string>
<string name="fcError" msgid="5325116502080221346">"Пробл. підключення чи недійсний ідентифікатор."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -373,8 +361,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Робити знімки екрана"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Може робити знімки екрана."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"<xliff:g id="DREAM_NAME">%1$s</xliff:g> (попередній перегляд)"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"закрити"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"вимикати чи змін. рядок стану"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Дозволяє програмі вимикати рядок стану чи додавати та видаляти піктограми системи."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"відображатися як рядок стану"</string>
@@ -2159,6 +2146,10 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Сповіщення про програму"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Режим енергозбереження ввімкнено"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Заряд використовується економно, щоб подовжити час роботи акумулятора"</string>
+ <!-- no translation found for dynamic_mode_notification_title_v2 (5072385242078021152) -->
+ <skip />
+ <!-- no translation found for dynamic_mode_notification_summary_v2 (2142444344663147938) -->
+ <skip />
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Режим енергозбереження"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Режим енергозбереження вимкнено."</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Телефон має достатньо заряду акумулятора. Функції вже не обмежено."</string>
@@ -2233,10 +2224,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Перейти в робочий додаток?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Ваша організація дозволяє телефонувати лише з робочих додатків"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Ваша організація дозволяє надсилати повідомлення лише з робочих додатків"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Ви можете телефонувати лише з особистого додатка Телефон. Такі дзвінки реєструватимуться у вашій особистій історії викликів."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"Ви можете надсилати SMS лише з особистого додатка Повідомлення."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Використати особистий веб-переглядач"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Використати робочий веб-переглядач"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Телефонувати"</string>
@@ -2416,8 +2405,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Робочий профіль 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Тестовий профіль"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Спільний профіль"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Робочий профіль"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Приватний простір"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Копія профілю"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Спільний профіль"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Чутливий вміст сповіщення приховано"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"З міркувань безпеки вміст додатка приховано під час показу екрана"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Автоматично підключено до супутника"</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index a2b7327..ed1a358 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> بعد از <xliff:g id="TIME_DELAY">{2}</xliff:g> سیکنڈ"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g> : فارورڈ نہیں کی گئی"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: فارورڈ نہیں کی گئی"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"موبائل نیٹ ورک سیکیورٹی"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"غیر مرموز کردہ نیٹ ورکس کے لیے مرموز کاری، اطلاعات"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"آلہ ID تک رسائی کی گئی"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"<xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> میں، قریبی نیٹ ورک نے آپ کے <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> SIM کا استعمال کرتے ہوئے آپ کے آلے کی منفرد ID (IMSI یا IMEI) ریکارڈ کی"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"<xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> میں، آپ کے <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> SIM استعمال کرتے ہوئے قریبی نیٹ ورک نے آپ کے آلے کی منفرد ID (IMSI یا IMEI) کو ریکارڈ کیا۔\n\nاس کا مطلب ہے کہ آپ کا مقام، سرگرمی یا شناخت لاگ ان ہو چکی ہیں۔ یہ عام بات ہے لیکن رازداری کے بارے میں فکر مند لوگوں کے لیے ایک مسئلہ ہو سکتا ہے۔"</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"مرموز کردہ نیٹ ورک <xliff:g id="NETWORK_NAME">%1$s</xliff:g> سے منسلک ہے"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM کا کنکشن اب بہت محفوظ ہے"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"غیر مرموز کردہ نیٹ ورک سے منسلک ہے"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"آپ کے <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM استعمال کرتے ہوئے کالز، پیغامات اور ڈیٹا کو فی الحال زیادہ خطرہ لاحق ہے"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"آپ کے <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM استعمال کرتے ہوئے کاز، پیغامات اور ڈیٹا کو فی الحال زیادہ خطرہ لاحق ہے۔\n\nآپ کا کنکشن دوبارہ مرموز ہونے پر آپ کو دوسری اطلاع موصول ہوگی۔"</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"موبائل نیٹ ورک سیکیورٹی کی ترتیبات"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"مزید جانیں"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"سمجھ آ گئی"</string>
<string name="fcComplete" msgid="1080909484660507044">"خصوصیت کوڈ مکمل۔"</string>
<string name="fcError" msgid="5325116502080221346">"کنکشن مسئلہ یا غلط خصوصیت کوڈ۔"</string>
<string name="httpErrorOk" msgid="6206751415788256357">"ٹھیک ہے"</string>
@@ -371,8 +359,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"اسکرین شاٹ لیں"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ڈسپلے کا اسکرین شاٹ لیا جا سکتا ہے۔"</string>
<string name="dream_preview_title" msgid="5570751491996100804">"پیش منظر، <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"برخاست کریں"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"اسٹیٹس بار کو غیر فعال یا اس میں ترمیم کریں"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"ایپ کو اسٹیٹس بار غیر فعال کرنے یا سسٹم آئیکنز شامل کرنے اور ہٹانے کی اجازت دیتا ہے۔"</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"بطور اسٹیٹس بار کام لیں"</string>
@@ -2157,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"روٹین موڈ معلومات کی اطلاع"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"بیٹری سیور کو آن کیا گیا"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"بیٹری لائف کو بڑھانے کے لیے بیٹری کے استعمال کو کم کیا جا رہا ہے"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"بیٹری سیور آن ہے"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"بیٹری لائف کو بڑھانے کے لیے بیٹری سیور کو آن کر دیا گیا ہے"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"بیٹری سیور"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"بیٹری سیور کو آف کر دیا گیا"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"فون میں کافی چارج ہے۔ خصوصیات پر اب پابندی نہیں ہے۔"</string>
@@ -2231,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"ورک ایپ پر سوئچ کریں؟"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"آپ کی تنظیم آپ کو صرف ورک ایپس سے کالز کرنے کی اجازت دیتی ہے"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"آپ کی تنظیم آپ کو صرف ورک ایپس سے پیغامات بھیجنے کی اجازت دیتی ہے"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"آپ صرف اپنی ذاتی فون ایپ سے فون کالز کر سکتے ہیں۔ ذاتی فون سے کی گئی کالز آپ کی ذاتی کال کی سرگزشت میں شامل کر دی جائیں گی۔"</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"آپ صرف اپنی ذاتی پیغامات ایپ سے SMS پیغامات بھیج سکتے ہیں۔"</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"ذاتی براؤزر استعمال کریں"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"ورک براؤزر استعمال کریں"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"کال کریں"</string>
@@ -2414,6 +2401,10 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"تیسری دفتری پروفائل"</string>
<string name="profile_label_test" msgid="9168641926186071947">"ٹیسٹ"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"کمیونل"</string>
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"دفتری پروفائل"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"پرائیویٹ اسپیس"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"کلون"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"کمیونل"</string>
<string name="redacted_notification_message" msgid="1520587845842228816">"حساس اطلاعی مواد چھپا ہوا ہے"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"سیکیورٹی کے مد نظر ایپ کا مواد اسکرین کے اشتراک سے چھپا ہوا ہے"</string>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index b35c33b..4ddd368 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> soniyadan so‘ng"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Yo‘naltirilmadi"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: yo‘naltirilmadi"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Mobil tarmoq xavfsizligi"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Shifrlash, shifrlanmagan tarmoqlar haqidagi bildirishnomalar"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"Qurilma identifikatoriga ruxsat olingan"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"<xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> da SIM karta (<xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>) ishlatilganda atrofdagi tarmoqda qurilmaning unikal identifikatori (IMSI yoki IMEI) qayd qilingan"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"<xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g> da SIM karta (<xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>) ishlatilganda atrofdagi tarmoqda qurilmaning unikal identifikatori (IMSI yoki IMEI) qayd qilingan.\n\nJoylashuvingiz, faolligingiz yoki kimligingiz qayd qilingan. Bu odatiy holat boʻlsa ham, maxfiyligi haqida xavotirlanuvchi odamlar uchun muammo boʻlishi mumkin."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Shifrlangan tarmoqqa (<xliff:g id="NETWORK_NAME">%1$s</xliff:g>) ulandi"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"Endi SIM karta (<xliff:g id="NETWORK_NAME">%1$s</xliff:g>) aloqasi yanada xavfsiz"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Shifrlanmagan tarmoqqa ulandi"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Hozir SIM karta (<xliff:g id="NETWORK_NAME">%1$s</xliff:g>) orqali chaqiruvlar, xabarlar va maʼlumotlar himoyasi zaif"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Hozir SIM karta (<xliff:g id="NETWORK_NAME">%1$s</xliff:g>) orqali chaqiruvlar, xabarlar va maʼlumotlar himoyasi zaif.\n\nAloqa qayta shifrlanganda boshqa bildirishnoma olasiz."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Mobil tarmoq xavfsizligi sozlamalari"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Batafsil"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"OK"</string>
<string name="fcComplete" msgid="1080909484660507044">"Maxsus kod bajarildi."</string>
<string name="fcError" msgid="5325116502080221346">"Tarmoqda xato yoki maxsus kod noto‘g‘ri."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -2156,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Kun tartibi rejimi haqidagi bildirishnoma"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Quvvat tejalishi yoqildi"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Batareya tejalganda batareya quvvati uzoqroq vaqtga yetadi"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"Quvvat tejash rejimi yoniq"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"Batareya quvvatini uzaytirish uchun Quvvat tejash yoqilgan"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Quvvat tejash"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Quvvat tejash rejimi faolsizlantirildi"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Telefon yetarli quvvatlandi. Funksiyalar endi cheklovlarsiz ishlaydi."</string>
@@ -2230,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Ishga oid ilovaga almashtirilsinmi?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Tashkilotingiz faqat ishga oid ilovalar orqali chaqiruvga ruxsat beradi"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Tashkilotingiz faqat ishga oid ilovalar orqali xabarlar yuborishga ruxsat beradi"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Siz faqat shaxsiy Telefon ilovasi orqali telefon qila olasiz. Shaxsiy Telefon orqali amalga oshgan chaqiruvlar shaxsiy chaqiruvlar tarixida saqlanadi."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"Siz faqat shaxsiy Xabarlar ilovasi orqali SMS yubora olasiz."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Shaxsiy brauzerdan foydalanish"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Ishga oid brauzerdan foydalanish"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Chaqiruv"</string>
@@ -2406,15 +2394,18 @@
<string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Klaviatura terilmasi bunga sozlandi: <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… Oʻzgartirish uchun ustiga bosing."</string>
<string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Tashqi klaviaturalar sozlandi"</string>
<string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Klaviaturalarni ochish uchun ustiga bosing"</string>
- <string name="profile_label_private" msgid="6463418670715290696">"Yopiq"</string>
+ <string name="profile_label_private" msgid="6463418670715290696">"Maxfiy"</string>
<string name="profile_label_clone" msgid="769106052210954285">"Nusxasini yaratish"</string>
<string name="profile_label_work" msgid="3495359133038584618">"Ish"</string>
<string name="profile_label_work_2" msgid="4691533661598632135">"Ish 2"</string>
<string name="profile_label_work_3" msgid="4834572253956798917">"Ish 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Umumiy"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Ish profili"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Maxfiy makon"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Nusxalash"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Umumiy"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Bildirishnomadagi maxfiy axborot berkitildi"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Ekran namoyishida xavfsizlik maqsadida ilova kontenti berkitildi"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Sputnikka avtomatik ulandi"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index e7c94d6..c633c2a 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> sau <xliff:g id="TIME_DELAY">{2}</xliff:g> giây"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Không được chuyển tiếp"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Không được chuyển tiếp"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Bảo mật mạng di động"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Mã hoá, thông báo cho mạng chưa được mã hoá"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"Mã thiết bị được truy cập"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"Vào <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, một mạng lân cận đã ghi nhận mã nhận dạng duy nhất của thiết bị của bạn (IMSI hoặc IMEI) trong lúc sử dụng SIM <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> của bạn"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"Vào <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, một mạng lân cận đã ghi nhận mã nhận dạng duy nhất của thiết bị của bạn (IMSI hoặc IMEI) trong lúc sử dụng SIM <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> của bạn.\n\nTức là vị trí, hoạt động hoặc danh tính của bạn đã được ghi lại. Đây là một phương thức thông dụng nhưng có thể trở thành vấn đề đối với những ai lo ngại về quyền riêng tư."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Đã kết nối với mạng <xliff:g id="NETWORK_NAME">%1$s</xliff:g> đã mã hoá"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"Kết nối SIM <xliff:g id="NETWORK_NAME">%1$s</xliff:g> nay an toàn hơn"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Đã kết nối với mạng chưa được mã hoá"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Cuộc gọi, tin nhắn và dữ liệu hiện dễ bị tấn công trong lúc sử dụng SIM <xliff:g id="NETWORK_NAME">%1$s</xliff:g> của bạn."</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Cuộc gọi, tin nhắn và dữ liệu hiện dễ bị tấn công trong lúc sử dụng SIM <xliff:g id="NETWORK_NAME">%1$s</xliff:g> của bạn.\n\nKhi kết nối của bạn được mã hoá lại, bạn sẽ nhận được một thông báo khác."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Chế độ bảo mật mạng di động"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Tìm hiểu thêm"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"Tôi hiểu"</string>
<string name="fcComplete" msgid="1080909484660507044">"Mã tính năng đã hoàn tất."</string>
<string name="fcError" msgid="5325116502080221346">"Sự cố kết nối hoặc mã tính năng không hợp lệ."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -371,8 +359,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Chụp ảnh màn hình"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Có thể chụp ảnh màn hình."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Bản xem trước, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"đóng"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"vô hiệu hóa hoặc sửa đổi thanh trạng thái"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Cho phép ứng dụng vô hiệu hóa thanh trạng thái hoặc thêm và xóa biểu tượng hệ thống."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"trở thành thanh trạng thái"</string>
@@ -2157,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Thông báo cung cấp thông tin về chế độ sạc thông thường"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Đã bật Trình tiết kiệm pin"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Giảm mức sử dụng pin để kéo dài thời lượng pin"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"Trình tiết kiệm pin đang bật"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"Trình tiết kiệm pin được bật để kéo dài thời lượng pin"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Trình tiết kiệm pin"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Trình tiết kiệm pin đã tắt"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Điện thoại còn đủ pin. Các tính năng không bị hạn chế nữa."</string>
@@ -2231,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Chuyển sang ứng dụng công việc?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Tổ chức của bạn chỉ cho phép bạn gọi điện bằng ứng dụng công việc"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Tổ chức của bạn chỉ cho phép bạn gửi tin nhắn bằng ứng dụng công việc"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Bạn chỉ có thể gọi điện qua ứng dụng Điện thoại cá nhân của mình. Cuộc gọi được thực hiện bằng ứng dụng Điện thoại cá nhân sẽ được thêm vào nhật ký cuộc gọi cá nhân của bạn."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"Bạn chỉ có thể gửi tin nhắn SMS qua ứng dụng Tin nhắn cá nhân của mình."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Dùng trình duyệt cá nhân"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Dùng trình duyệt công việc"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Gọi"</string>
@@ -2414,8 +2401,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Công việc 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Kiểm thử"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Dùng chung"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Hồ sơ công việc"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Không gian riêng tư"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Nhân bản"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Dùng chung"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Đã ẩn nội dung thông báo nhạy cảm"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Nội dung ứng dụng bị ẩn khỏi tính năng chia sẻ màn hình vì lý do bảo mật"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Đã tự động kết nối với vệ tinh"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 10ceb5b..f16881a 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:<xliff:g id="TIME_DELAY">{2}</xliff:g>秒后<xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:无法转接"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:无法转接"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"移动网络安全"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"加密,连接到未加密网络时通知"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"有网络获取了设备 ID"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"<xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>,当您使用<xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> SIM 卡时,一个附近的网络记录了您设备的唯一 ID(IMSI 或 IMEI)"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"<xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>,当您使用<xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> SIM 卡时,一个附近的网络记录了您设备的唯一 ID(IMSI 或 IMEI)。\n\n这意味着您的位置信息、活动或身份信息都被记录了。这是常见做法,但对注重隐私的人来说可能是一个问题。"</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"连接到了名为“<xliff:g id="NETWORK_NAME">%1$s</xliff:g>”的加密网络"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM 卡连接现在更安全了"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"连接到了一个未加密的网络"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"目前,当您使用<xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM 卡时,通话、消息和数据更易受到攻击"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"目前,当您使用<xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM 卡时,通话、消息和数据更易受到攻击。\n\n当您的连接再次加密时,您会另收到一条通知。"</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"移动网络安全设置"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"了解详情"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"知道了"</string>
<string name="fcComplete" msgid="1080909484660507044">"功能代码已拨完。"</string>
<string name="fcError" msgid="5325116502080221346">"出现连接问题或功能代码无效。"</string>
<string name="httpErrorOk" msgid="6206751415788256357">"确定"</string>
@@ -2156,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"日常安排模式信息通知"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"省电模式已开启"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"降低电池用量以延长电池续航时间"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"省电模式已开启"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"已开启省电模式以延长电池续航时间"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"省电模式"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"省电模式已关闭"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"手机电量充足。各项功能不再受限。"</string>
@@ -2230,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"切换到工作应用?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"贵组织仅允许您通过工作应用拨打电话"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"贵组织仅允许您通过工作应用发送消息"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"您只能使用个人“电话”应用打电话。用个人“电话”进行的通话将会添加到您的个人通话记录中。"</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"您只能使用个人“信息”应用发送短信。"</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"使用个人浏览器"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"使用工作浏览器"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"拨打电话"</string>
@@ -2413,8 +2401,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"工作 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"测试"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"共用"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"工作资料"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"私密空间"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"克隆"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"共用"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"已隐藏敏感通知内容"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"为安全起见而在屏幕共享画面中处于隐藏状态的应用内容"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"自动连接到卫星"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 541ea63..efa260f 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> 於 <xliff:g id="TIME_DELAY">{2}</xliff:g> 秒後轉接"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:尚未轉接"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:尚未轉接"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"流動網絡安全"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"加密 (網絡未加密通知)"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"已存取裝置 ID"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"在 <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>,附近網絡使用你的 「<xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>」SIM 卡時,記錄了你裝置的獨特 ID (IMSI 或 IMEI)。"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"在 <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>,附近網絡使用你的 「<xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>」SIM 卡時,記錄了你裝置的獨特 ID (IMSI 或 IMEI)。\n\n這代表附近網絡記錄了你的位置、活動或身分資料。雖然這種情況很常見,但對注重私隱的人可能構成問題。"</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"已連線至已加密的網絡 <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"現在連線「<xliff:g id="NETWORK_NAME">%1$s</xliff:g>」SIM 卡更加安全"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"已連線至未加密的網絡"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"目前使用「<xliff:g id="NETWORK_NAME">%1$s</xliff:g>」SIM 卡時,通話、訊息和資料較容易受到攻擊"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"目前使用「<xliff:g id="NETWORK_NAME">%1$s</xliff:g>」SIM 卡時,通話、訊息和資料較容易受到攻擊。\n\n連線再次加密時,你會收到另一個通知。"</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"流動網絡安全設定"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"瞭解詳情"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"知道了"</string>
<string name="fcComplete" msgid="1080909484660507044">"功能碼輸入完成。"</string>
<string name="fcError" msgid="5325116502080221346">"連線問題或功能碼無效。"</string>
<string name="httpErrorOk" msgid="6206751415788256357">"確定"</string>
@@ -371,8 +359,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"擷取螢幕擷圖"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"可以擷取螢幕截圖。"</string>
<string name="dream_preview_title" msgid="5570751491996100804">"預覽,<xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"關閉"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"停用或修改狀態列"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"允許應用程式停用狀態列,並可新增或移除系統圖示。"</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"成為狀態列"</string>
@@ -2157,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"「日常安排模式」資料通知"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"已開啟「慳電模式」"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"減少用電可延長電池壽命"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"「慳電模式」已開啟"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"已開啟「慳電模式」,以延長電池壽命"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"慳電模式"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"已關閉慳電模式"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"手機電量充足。各項功能已不再受限。"</string>
@@ -2231,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"要切換至工作應用程式嗎?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"你的機構只允許你透過工作應用程式打電話"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"你的機構只允許你透過工作應用程式傳送訊息"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"你只可使用個人「電話」應用程式撥打電話。透過個人「電話」應用程式撥出的電話會在個人通話記錄中顯示。"</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"使用個人「訊息」應用程式時,只能傳送短訊。"</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"使用個人瀏覽器"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"使用工作瀏覽器"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"打電話"</string>
@@ -2414,8 +2401,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"工作 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"測試"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"共用"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"工作設定檔"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"私人空間"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"複製"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"共用"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"已隱藏敏感通知內容"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"為安全起見,應用程式內容已從分享螢幕畫面隱藏"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"已自動連線至衛星"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 8720a9d..0c18193 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:<xliff:g id="TIME_DELAY">{2}</xliff:g> 秒後 <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:未轉接"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:未轉接"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"行動網路安全性"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"加密 (網路未加密通知)"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"已存取裝置 ID"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"在 <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>,鄰近網路使用你的「<xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>」SIM 卡時,記錄了你的裝置專屬 ID (IMSI 或 IMEI)"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"在 <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>,鄰近網路使用你的「<xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>」SIM 卡時,記錄了你的裝置專屬 ID (IMSI 或 IMEI)。\n\n這代表鄰近網路記錄了你的位置、活動或身分資訊。儘管這種情況很常見,但注重隱私的人可能會認為這是個問題。"</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"已連上加密網路「<xliff:g id="NETWORK_NAME">%1$s</xliff:g>」"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"現在連上「<xliff:g id="NETWORK_NAME">%1$s</xliff:g>」SIM 卡更加安全"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"已連上未加密網路"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"目前使用「<xliff:g id="NETWORK_NAME">%1$s</xliff:g>」SIM 卡時,通話、訊息和資料較容易受到攻擊"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"目前使用「<xliff:g id="NETWORK_NAME">%1$s</xliff:g>」SIM 卡時,通話、訊息和資料較容易受到攻擊。\n\n連線再次加密時,你會收到另一則通知。"</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"行動網路安全性設定"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"瞭解詳情"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"我知道了"</string>
<string name="fcComplete" msgid="1080909484660507044">"功能碼輸入完成。"</string>
<string name="fcError" msgid="5325116502080221346">"連線發生問題或功能碼無效。"</string>
<string name="httpErrorOk" msgid="6206751415788256357">"確定"</string>
@@ -371,8 +359,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"擷取螢幕畫面"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"可以擷取螢幕畫面。"</string>
<string name="dream_preview_title" msgid="5570751491996100804">"預覽,<xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"關閉"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"停用或變更狀態列"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"允許應用程式停用狀態列,並可新增或移除系統圖示。"</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"以狀態列顯示"</string>
@@ -2157,6 +2144,10 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"日常安排模式資訊通知"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"已開啟省電模式"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"降低電池用量,以便延長電池續航力"</string>
+ <!-- no translation found for dynamic_mode_notification_title_v2 (5072385242078021152) -->
+ <skip />
+ <!-- no translation found for dynamic_mode_notification_summary_v2 (2142444344663147938) -->
+ <skip />
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"省電模式"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"省電模式已關閉"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"手機電力充足,各項功能不再受到限制。"</string>
@@ -2231,10 +2222,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"要切換到工作應用程式嗎?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"貴機構僅允許透過工作應用程式撥打電話"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"貴機構僅允許透過工作應用程式傳送訊息"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"只能使用個人「電話」應用程式撥打電話。透過個人「電話」應用程式撥出的電話會顯示在個人通話記錄中。"</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"使用個人的訊息應用程式時,只能傳送簡訊。"</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"使用個人瀏覽器"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"使用工作瀏覽器"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"撥號"</string>
@@ -2414,8 +2403,11 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"工作 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"測試"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"通用"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"工作資料夾"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"私人空間"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"複製"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"共通"</string>
+ <string name="redacted_notification_message" msgid="1520587845842228816">"系統已隱藏含有私密資訊的通知內容"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"為安全起見,分享螢幕畫面未顯示應用程式內容"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"已自動連上衛星"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 7f14f04..7dc3fd6 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -153,31 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> emuva kwamasekhondi angu-<xliff:g id="TIME_DELAY">{2}</xliff:g>"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Akudlulisiwe"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: akudlulisiwe"</string>
- <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
- <skip />
- <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
- <skip />
- <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
- <skip />
- <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
- <skip />
- <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
- <skip />
- <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
- <skip />
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Ezokuphepha kwenethiwekhi yeselula"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Ukubethela, izaziso zamanethiwekhi angabetheliwe"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"I-ID yedivayisi ifinyelelwe"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"Ngo-<xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, inethiwekhi eseduze irekhode i-ID ehlukile yedivayisi yakho (i-IMSI noma i-IMEI) ngenkathi usebenzisa i-SIM yakho ye-<xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"Ngo-<xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, inethiwekhi eseduze irekhode i-ID ehlukile yedivayisi yakho (i-IMSI noma i-IMEI) ngenkathi usebenzisa i-SIM yakho ye-<xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g>.\n\nLokhu kusho ukuthi indawo yakho, umsebenzi, noma ubuwena bufakiwe. Lokhu kuwumkhuba ovamile kodwa kungase kube inkinga kubantu abathintekayo mayelana nobumfihlo."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Ixhumeke kunethiwekhi ebethelwe ye-<xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"Uxhumo lwe-SIM ye-<xliff:g id="NETWORK_NAME">%1$s</xliff:g> luvikeleke kakhulu manje"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Ixhumeke kunethiwekhi engabetheliwe"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Amakholi, imilayezo, nedatha okwamanje zisengozini kakhulu ngenkathi usebenzisa i-SIM yakho ye-<xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Amakholi, imilayezo, nedatha okwamanje zisengozini kakhulu ngenkathi usebenzisa i-SIM yakho ye-<xliff:g id="NETWORK_NAME">%1$s</xliff:g>.\n\nUma uxhumano lwakho lubethelwa futhi, uzothola esinye isaziso."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Amasethingi ezokuphepha kwenethiwekhi yeselula"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Funda kabanzi"</string>
- <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
- <skip />
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"Ngiyezwa"</string>
<string name="fcComplete" msgid="1080909484660507044">"Ikhodi yesici iqedile."</string>
<string name="fcError" msgid="5325116502080221346">"Inkinga yoxhumano noma ikhodi yesici engalungile."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"KULUNGILE"</string>
@@ -2156,6 +2144,8 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Isaziso solwazi lwe-Routine Mode"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Isilondolozi Sebhethri sivuliwe"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Ukwehlisa ukusetshenziswa kwebhethri ukuze kunwetshiswe impilo yebhethri"</string>
+ <string name="dynamic_mode_notification_title_v2" msgid="5072385242078021152">"Isilondolozi sebhethri sivuliwe"</string>
+ <string name="dynamic_mode_notification_summary_v2" msgid="2142444344663147938">"Isilondolozi Sebhethri sivuliwe ukuze kunwetshwe impilo yebhethri"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Isilondolozi sebhethri"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Isilondolozi sebhethri sivaliwe"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Ifoni inokushajwa okwanele. Izici azisakhawulelwe."</string>
@@ -2230,10 +2220,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Shintshela ku-app yasemsebenzini?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Inhlangano yakho ikuvumela kuphela ukuthi wenze amakholi ngama-app asemsebenzini"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Inhlangano yakho ikuvumela ukuthumela imilayezo kusuka kuma-app omsebenzi kuphela"</string>
- <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
- <skip />
- <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
- <skip />
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"Ungenza amakholi wefoni kuphela nge-app yakho Yefoni yomuntu siqu. Amakholi enziwe Ngefoni yomuntu siqu azongezwa kumlando wakho wekholi womuntu siqu."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"Ungathumela imiyalezo ye-SMS ukusuka ku-app yomuntu siqu ye-Messages kuphela."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Sebenzisa isiphequluli somuntu siqu"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Sebenzisa isiphequluli somsebenzi"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Fona"</string>
@@ -2413,6 +2401,10 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Umsebenzi 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Hlola"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Okomphakathi"</string>
+ <string name="accessibility_label_managed_profile" msgid="3366526886209832641">"Iphrofayela yomsebenzi"</string>
+ <string name="accessibility_label_private_profile" msgid="1436459319135548969">"Indawo engasese"</string>
+ <string name="accessibility_label_clone_profile" msgid="7579118375042398784">"Yenza i-Clone"</string>
+ <string name="accessibility_label_communal_profile" msgid="1437173163111334791">"Okomphakathi"</string>
<string name="redacted_notification_message" msgid="1520587845842228816">"Okuqukethwe kwesaziso esizwelayo kufihliwe"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Okuqukethwe kwe-app kufihliwe kusuka ekwabelaneni kwesikrini ngokuvikelwa"</string>
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 5e900f7..27b756d 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -842,7 +842,8 @@
that created the task, and therefore there will only be one instance of this activity
in a task. In contrast to the {@code singleTask} launch mode, this activity can be
started in multiple instances in different tasks if the
- {@code FLAG_ACTIVITY_MULTIPLE_TASK} or {@code FLAG_ACTIVITY_NEW_DOCUMENT} is set.-->
+ {@code FLAG_ACTIVITY_MULTIPLE_TASK} or {@code FLAG_ACTIVITY_NEW_DOCUMENT} is set.
+ This enum value is introduced in API level 31. -->
<enum name="singleInstancePerTask" value="4" />
</attr>
<!-- Specify the orientation an activity should be run in. If not
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 877d11e..edaf8b5 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -6093,6 +6093,18 @@
<!-- Whether displaying letterbox education is enabled for letterboxed fullscreen apps. -->
<bool name="config_letterboxIsEducationEnabled">false</bool>
+ <!-- The width in dp to use to detect vertical thin letterboxing.
+ If W is the available width and w is the letterbox width, an app
+ is thin letterboxed if the value here is < (W - w) / 2
+ If the value is < 0 the thin letterboxing policy is disabled -->
+ <dimen name="config_letterboxThinLetterboxWidthDp">-1dp</dimen>
+
+ <!-- The height in dp to use to detect horizontal thin letterboxing
+ If H is the available height and h is the letterbox height, an app
+ is thin letterboxed if the value here is < (H - h) / 2
+ If the value is < 0 the thin letterboxing policy is disabled -->
+ <dimen name="config_letterboxThinLetterboxHeightDp">-1dp</dimen>
+
<!-- Default min aspect ratio for unresizable apps which are eligible for size compat mode.
Values <= 1.0 will be ignored. Activity min/max aspect ratio restrictions will still be
espected so this override can control the maximum screen area that can be occupied by
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 54c9479..1fca4f8 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -5859,6 +5859,10 @@
<string name="dynamic_mode_notification_title">Battery Saver turned on</string>
<!-- Summary of notification letting users know why battery saver was turned on automatically [CHAR_LIMIT=NONE]-->
<string name="dynamic_mode_notification_summary">Reducing battery usage to extend battery life</string>
+ <!-- Title of notification letting users know why battery saver was turned on automatically [CHAR_LIMIT=NONE]-->
+ <string name="dynamic_mode_notification_title_v2">Battery Saver is on</string>
+ <!-- Summary of notification letting users know why battery saver was turned on automatically [CHAR_LIMIT=NONE]-->
+ <string name="dynamic_mode_notification_summary_v2">Battery Saver is turned on to extend battery life</string>
<!-- Battery saver strings -->
<!-- The user visible name of the notification channel for battery saver notifications [CHAR_LIMIT=80] -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 972d8df..36542ee 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1387,6 +1387,7 @@
<java-symbol type="drawable" name="platlogo" />
<java-symbol type="drawable" name="stat_notify_sync_error" />
<java-symbol type="drawable" name="stat_notify_wifi_in_range" />
+ <java-symbol type="drawable" name="ic_thread_network" />
<java-symbol type="drawable" name="ic_wifi_signal_0" />
<java-symbol type="drawable" name="ic_wifi_signal_1" />
<java-symbol type="drawable" name="ic_wifi_signal_2" />
@@ -4261,7 +4262,9 @@
<java-symbol type="string" name="battery_saver_charged_notification_summary" />
<java-symbol type="string" name="dynamic_mode_notification_channel_name" />
<java-symbol type="string" name="dynamic_mode_notification_title" />
+ <java-symbol type="string" name="dynamic_mode_notification_title_v2" />
<java-symbol type="string" name="dynamic_mode_notification_summary" />
+ <java-symbol type="string" name="dynamic_mode_notification_summary_v2" />
<java-symbol type="drawable" name="ic_battery" />
<java-symbol type="bool" name="config_skipSensorAvailable" />
@@ -4714,6 +4717,8 @@
<java-symbol type="integer" name="config_letterboxDefaultPositionForTabletopModeReachability" />
<java-symbol type="bool" name="config_letterboxIsPolicyForIgnoringRequestedOrientationEnabled" />
<java-symbol type="bool" name="config_letterboxIsEducationEnabled" />
+ <java-symbol type="dimen" name="config_letterboxThinLetterboxWidthDp" />
+ <java-symbol type="dimen" name="config_letterboxThinLetterboxHeightDp" />
<java-symbol type="dimen" name="config_letterboxDefaultMinAspectRatioForUnresizableApps" />
<java-symbol type="bool" name="config_letterboxIsSplitScreenAspectRatioForUnresizableAppsEnabled" />
<java-symbol type="bool" name="config_letterboxIsDisplayAspectRatioForFixedOrientationLetterboxEnabled" />
diff --git a/core/tests/coretests/src/android/view/ImeBackAnimationControllerTest.java b/core/tests/coretests/src/android/view/ImeBackAnimationControllerTest.java
index c00ebe4..57bbb1c 100644
--- a/core/tests/coretests/src/android/view/ImeBackAnimationControllerTest.java
+++ b/core/tests/coretests/src/android/view/ImeBackAnimationControllerTest.java
@@ -241,6 +241,23 @@
});
}
+ @Test
+ public void testOnBackInvokedHidesImeEvenIfInsetsControlCancelled() {
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+ // start back gesture
+ WindowInsetsAnimationControlListener animationControlListener = startBackGesture();
+
+ // simulate ImeBackAnimationController not receiving control (e.g. due to split screen)
+ animationControlListener.onCancelled(mWindowInsetsAnimationController);
+
+ // commit back gesture
+ mBackAnimationController.onBackInvoked();
+
+ // verify that InsetsController#hide is called
+ verify(mInsetsController, times(1)).hide(ime());
+ });
+ }
+
private WindowInsetsAnimationControlListener startBackGesture() {
// start back gesture
mBackAnimationController.onBackStarted(new BackEvent(0f, 0f, 0f, EDGE_LEFT));
diff --git a/core/tests/coretests/src/android/view/ViewFrameRateTest.java b/core/tests/coretests/src/android/view/ViewFrameRateTest.java
index 32aec1a..0b1b40c 100644
--- a/core/tests/coretests/src/android/view/ViewFrameRateTest.java
+++ b/core/tests/coretests/src/android/view/ViewFrameRateTest.java
@@ -17,6 +17,7 @@
package android.view;
import static android.view.Surface.FRAME_RATE_CATEGORY_HIGH;
+import static android.view.Surface.FRAME_RATE_CATEGORY_HIGH_HINT;
import static android.view.Surface.FRAME_RATE_CATEGORY_LOW;
import static android.view.Surface.FRAME_RATE_CATEGORY_NORMAL;
import static android.view.Surface.FRAME_RATE_CATEGORY_NO_PREFERENCE;
@@ -196,7 +197,7 @@
@RequiresFlagsEnabled({FLAG_VIEW_VELOCITY_API,
FLAG_TOOLKIT_FRAME_RATE_VELOCITY_MAPPING_READ_ONLY,
FLAG_TOOLKIT_FRAME_RATE_VIEW_ENABLING_READ_ONLY})
- public void highVelocity140() throws Throwable {
+ public void highVelocity120() throws Throwable {
mActivityRule.runOnUiThread(() -> {
ViewGroup.LayoutParams layoutParams = mMovingView.getLayoutParams();
layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
@@ -208,7 +209,7 @@
mMovingView.setFrameContentVelocity(1_000_000_000f);
mMovingView.invalidate();
runAfterDraw(() -> {
- assertEquals(140f, mViewRoot.getLastPreferredFrameRate(), 0f);
+ assertEquals(120f, mViewRoot.getLastPreferredFrameRate(), 0f);
});
});
waitForAfterDraw();
@@ -488,16 +489,19 @@
waitForFrameRateCategoryToSettle();
for (int i = 0; i < 5; i++) {
int expectedCategory;
- if (i < 4) {
+ if (i < 2) {
// not intermittent yet.
// It takes 2 frames of intermittency before Views vote as intermittent.
- // It takes 4 more frames for the category to drop to the next category.
expectedCategory =
toolkitFrameRateDefaultNormalReadOnly() ? FRAME_RATE_CATEGORY_NORMAL
: FRAME_RATE_CATEGORY_HIGH;
} else {
// intermittent
- expectedCategory = FRAME_RATE_CATEGORY_NORMAL;
+ // Even though this is not a small View, step 3 is triggered by this flag, which
+ // brings intermittent to LOW
+ expectedCategory = toolkitFrameRateBySizeReadOnly()
+ ? FRAME_RATE_CATEGORY_LOW
+ : FRAME_RATE_CATEGORY_NORMAL;
}
mActivityRule.runOnUiThread(() -> {
mMovingView.invalidate();
@@ -561,6 +565,64 @@
assertEquals(0f, mViewRoot.getLastPreferredFrameRate(), 0f);
}
+ @Test
+ @RequiresFlagsEnabled({FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY,
+ FLAG_TOOLKIT_FRAME_RATE_VIEW_ENABLING_READ_ONLY
+ })
+ public void frameRateResetWithInvalidations() throws Throwable {
+ mMovingView.setRequestedFrameRate(120f);
+ waitForFrameRateCategoryToSettle();
+ mMovingView.setRequestedFrameRate(View.REQUESTED_FRAME_RATE_CATEGORY_NORMAL);
+
+ for (int i = 0; i < 120; i++) {
+ mActivityRule.runOnUiThread(() -> {
+ mMovingView.invalidate();
+ runAfterDraw(() -> {});
+ });
+ waitForAfterDraw();
+ }
+
+ assertEquals(0f, mViewRoot.getLastPreferredFrameRate(), 0f);
+ }
+
+ @Test
+ @RequiresFlagsEnabled({FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY,
+ FLAG_TOOLKIT_FRAME_RATE_VIEW_ENABLING_READ_ONLY
+ })
+ public void testQuickTouchBoost() throws Throwable {
+ mActivityRule.runOnUiThread(() -> {
+ mMovingView.setRequestedFrameRate(View.REQUESTED_FRAME_RATE_CATEGORY_LOW);
+ ViewGroup.LayoutParams layoutParams = mMovingView.getLayoutParams();
+ layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
+ layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT;
+ mMovingView.setLayoutParams(layoutParams);
+ mMovingView.setOnClickListener((v) -> {});
+ });
+ waitForFrameRateCategoryToSettle();
+ mActivityRule.runOnUiThread(() -> assertEquals(FRAME_RATE_CATEGORY_LOW,
+ mViewRoot.getLastPreferredFrameRateCategory()));
+ int[] position = new int[2];
+ mActivityRule.runOnUiThread(() -> {
+ mMovingView.getLocationOnScreen(position);
+ position[0] += mMovingView.getWidth() / 2;
+ position[1] += mMovingView.getHeight() / 2;
+ });
+ final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
+
+ long now = SystemClock.uptimeMillis();
+ MotionEvent down = MotionEvent.obtain(
+ now, // downTime
+ now, // eventTime
+ MotionEvent.ACTION_DOWN, // action
+ position[0], // x
+ position[1], // y
+ 0 // metaState
+ );
+ down.setSource(InputDevice.SOURCE_TOUCHSCREEN);
+ instrumentation.sendPointerSync(down);
+ assertEquals(FRAME_RATE_CATEGORY_HIGH_HINT, mViewRoot.getLastPreferredFrameRateCategory());
+ }
+
private void runAfterDraw(@NonNull Runnable runnable) {
Handler handler = new Handler(Looper.getMainLooper());
mAfterDrawLatch = new CountDownLatch(1);
@@ -592,7 +654,6 @@
for (int i = 0; i < 5 || mViewRoot.getIsFrameRateBoosting(); i++) {
final CountDownLatch drawLatch = new CountDownLatch(1);
- // Now that it is small, any invalidation should have a normal category
ViewTreeObserver.OnDrawListener listener = drawLatch::countDown;
mActivityRule.runOnUiThread(() -> {
@@ -604,5 +665,12 @@
mActivityRule.runOnUiThread(
() -> mMovingView.getViewTreeObserver().removeOnDrawListener(listener));
}
+ // after boosting is complete, wait for one more draw cycle to ensure the boost isn't
+ // the last frame rate set
+ mActivityRule.runOnUiThread(() -> {
+ mMovingView.invalidate();
+ runAfterDraw(() -> {});
+ });
+ waitForAfterDraw();
}
}
diff --git a/core/tests/coretests/src/android/view/ViewRootImplTest.java b/core/tests/coretests/src/android/view/ViewRootImplTest.java
index 7c098f2..a7f8176 100644
--- a/core/tests/coretests/src/android/view/ViewRootImplTest.java
+++ b/core/tests/coretests/src/android/view/ViewRootImplTest.java
@@ -1174,9 +1174,16 @@
// Infrequent update
Thread.sleep(delay);
+
+ // Even though this is not a small View, step 3 is triggered by this flag, which
+ // brings intermittent to LOW
+ int intermittentExpected = toolkitFrameRateBySizeReadOnly()
+ ? FRAME_RATE_CATEGORY_LOW
+ : FRAME_RATE_CATEGORY_NORMAL;
+
sInstrumentation.runOnMainSync(() -> {
mView.invalidate();
- runAfterDraw(() -> assertEquals(FRAME_RATE_CATEGORY_NORMAL,
+ runAfterDraw(() -> assertEquals(intermittentExpected,
mViewRootImpl.getLastPreferredFrameRateCategory()));
});
waitForAfterDraw();
@@ -1184,7 +1191,7 @@
// When the View vote, it's still considered as intermittent update state
sInstrumentation.runOnMainSync(() -> {
mView.invalidate();
- runAfterDraw(() -> assertEquals(FRAME_RATE_CATEGORY_NORMAL,
+ runAfterDraw(() -> assertEquals(intermittentExpected,
mViewRootImpl.getLastPreferredFrameRateCategory()));
});
waitForAfterDraw();
diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityServiceConnectionImpl.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityServiceConnectionImpl.java
index 0b0fd66..b5c264c 100644
--- a/core/tests/coretests/src/android/view/accessibility/AccessibilityServiceConnectionImpl.java
+++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityServiceConnectionImpl.java
@@ -21,7 +21,9 @@
import android.accessibilityservice.IAccessibilityServiceConnection;
import android.accessibilityservice.IBrailleDisplayController;
import android.accessibilityservice.MagnificationConfig;
+import android.annotation.EnforcePermission;
import android.annotation.NonNull;
+import android.annotation.RequiresNoPermission;
import android.content.pm.ParceledListSlice;
import android.graphics.Region;
import android.hardware.usb.UsbDevice;
@@ -216,16 +218,19 @@
public void setAnimationScale(float scale) {}
+ @RequiresNoPermission
@Override
public void setInstalledAndEnabledServices(List<AccessibilityServiceInfo> infos)
throws RemoteException {
}
+ @RequiresNoPermission
@Override
public List<AccessibilityServiceInfo> getInstalledAndEnabledServices() throws RemoteException {
return null;
}
+ @RequiresNoPermission
@Override
public void attachAccessibilityOverlayToDisplay(
int interactionId,
@@ -233,6 +238,7 @@
SurfaceControl sc,
IAccessibilityInteractionConnectionCallback callback) {}
+ @RequiresNoPermission
@Override
public void attachAccessibilityOverlayToWindow(
int interactionId,
@@ -240,14 +246,21 @@
SurfaceControl sc,
IAccessibilityInteractionConnectionCallback callback) {}
+ @EnforcePermission(android.Manifest.permission.BLUETOOTH_CONNECT)
@Override
- public void connectBluetoothBrailleDisplay(String bluetoothAddress,
- IBrailleDisplayController controller) {}
+ public void connectBluetoothBrailleDisplay(
+ String bluetoothAddress, IBrailleDisplayController controller) {
+ connectBluetoothBrailleDisplay_enforcePermission();
+ }
+ @RequiresNoPermission
@Override
- public void connectUsbBrailleDisplay(UsbDevice usbDevice,
- IBrailleDisplayController controller) {}
+ public void connectUsbBrailleDisplay(
+ UsbDevice usbDevice, IBrailleDisplayController controller) {}
+ @EnforcePermission(android.Manifest.permission.MANAGE_ACCESSIBILITY)
@Override
- public void setTestBrailleDisplayData(List<Bundle> brailleDisplays) {}
+ public void setTestBrailleDisplayData(List<Bundle> brailleDisplays) {
+ setTestBrailleDisplayData_enforcePermission();
+ }
}
diff --git a/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java b/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java
index 1a8e75a..50d7f59 100644
--- a/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java
+++ b/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java
@@ -51,6 +51,7 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
+import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
@@ -372,6 +373,30 @@
}
@Test
+ public void onBackCancelled_calledBeforeOnBackStartedOfNewGesture() throws RemoteException {
+ mDispatcher.registerOnBackInvokedCallback(PRIORITY_DEFAULT, mCallback1);
+ OnBackInvokedCallbackInfo callbackInfo = assertSetCallbackInfo();
+
+ callbackInfo.getCallback().onBackStarted(mBackEvent);
+
+ waitForIdle();
+ verify(mCallback1).onBackStarted(any(BackEvent.class));
+ clearInvocations(mCallback1);
+
+ callbackInfo.getCallback().onBackCancelled();
+ waitForIdle();
+
+ // simulate start of new gesture while cancel animation is still running
+ callbackInfo.getCallback().onBackStarted(mBackEvent);
+ waitForIdle();
+
+ // verify that onBackCancelled is called before onBackStarted
+ InOrder orderVerifier = Mockito.inOrder(mCallback1);
+ orderVerifier.verify(mCallback1).onBackCancelled();
+ orderVerifier.verify(mCallback1).onBackStarted(any(BackEvent.class));
+ }
+
+ @Test
public void onDetachFromWindow_cancelCallbackAndIgnoreOnBackInvoked() throws RemoteException {
mDispatcher.registerOnBackInvokedCallback(PRIORITY_DEFAULT, mCallback1);
@@ -399,11 +424,11 @@
callbackInfo.getCallback().onBackStarted(mBackEvent);
waitForIdle();
- assertTrue(mDispatcher.isDispatching());
+ assertTrue(mDispatcher.isBackGestureInProgress());
callbackInfo.getCallback().onBackInvoked();
waitForIdle();
- assertFalse(mDispatcher.isDispatching());
+ assertFalse(mDispatcher.isBackGestureInProgress());
}
@Test
@@ -418,7 +443,7 @@
callbackInfo.getCallback().onBackStarted(mBackEvent);
waitForIdle();
- assertTrue(mDispatcher.isDispatching());
+ assertTrue(mDispatcher.isBackGestureInProgress());
assertTrue(mDispatcher.mTouchTracker.isActive());
main.runWithScissors(() -> mDispatcher.onMotionEvent(mMotionEvent), 100);
diff --git a/core/tests/packagemonitortests/src/com/android/internal/content/PackageMonitorTest.java b/core/tests/packagemonitortests/src/com/android/internal/content/PackageMonitorTest.java
index 03cb17e..991ada8 100644
--- a/core/tests/packagemonitortests/src/com/android/internal/content/PackageMonitorTest.java
+++ b/core/tests/packagemonitortests/src/com/android/internal/content/PackageMonitorTest.java
@@ -71,7 +71,7 @@
spyPackageMonitor.register(mMockContext, UserHandle.ALL, mMockHandler);
assertThat(spyPackageMonitor.getRegisteredHandler()).isEqualTo(mMockHandler);
- verify(mMockContext, times(1)).registerReceiverAsUser(any(), eq(UserHandle.ALL), any(),
+ verify(mMockContext, never()).registerReceiverAsUser(any(), eq(UserHandle.ALL), any(),
eq(null), eq(mMockHandler));
assertThrows(IllegalStateException.class,
@@ -97,7 +97,7 @@
@Test
public void testPackageMonitorNotRegisterWithoutSupportPackageRestartQuery() throws Exception {
- PackageMonitor spyPackageMonitor = spy(new TestPackageMonitor(false));
+ PackageMonitor spyPackageMonitor = spy(new TestPackageMonitor());
spyPackageMonitor.register(mMockContext, UserHandle.ALL, mMockHandler);
@@ -106,6 +106,16 @@
}
@Test
+ public void testPackageMonitorRegisterWithSupportPackageRestartQuery() throws Exception {
+ PackageMonitor spyPackageMonitor = spy(new TestPackageMonitor(true));
+
+ spyPackageMonitor.register(mMockContext, UserHandle.ALL, mMockHandler);
+
+ verify(mMockContext, times(1)).registerReceiverAsUser(any(), eq(UserHandle.ALL), any(),
+ eq(null), eq(mMockHandler));
+ }
+
+ @Test
public void testPackageMonitorDoHandlePackageEventUidRemoved() throws Exception {
PackageMonitor spyPackageMonitor = spy(new TestPackageMonitor());
@@ -318,8 +328,11 @@
verify(spyPackageMonitor, times(1)).onBeginPackageChanges();
verify(spyPackageMonitor, times(1))
.onPackageUpdateStarted(eq(FAKE_PACKAGE_NAME), eq(FAKE_PACKAGE_UID));
-
ArgumentCaptor<Bundle> argumentCaptor = ArgumentCaptor.forClass(Bundle.class);
+ verify(spyPackageMonitor, times(1))
+ .onPackageUpdateStartedWithExtras(eq(FAKE_PACKAGE_NAME), eq(FAKE_PACKAGE_UID),
+ argumentCaptor.capture());
+
verify(spyPackageMonitor, times(1)).onPackageDisappearedWithExtras(eq(FAKE_PACKAGE_NAME),
argumentCaptor.capture());
Bundle capturedExtras = argumentCaptor.getValue();
@@ -352,11 +365,16 @@
spyPackageMonitor.doHandlePackageEvent(intent);
verify(spyPackageMonitor, times(1)).onBeginPackageChanges();
+ ArgumentCaptor<Bundle> argumentCaptor = ArgumentCaptor.forClass(Bundle.class);
verify(spyPackageMonitor, times(1))
.onPackageUpdateStarted(eq(FAKE_PACKAGE_NAME), eq(FAKE_PACKAGE_UID));
+ verify(spyPackageMonitor, times(1))
+ .onPackageUpdateStartedWithExtras(eq(FAKE_PACKAGE_NAME), eq(FAKE_PACKAGE_UID),
+ argumentCaptor.capture());
verify(spyPackageMonitor, times(1)).onPackageModified(eq(FAKE_PACKAGE_NAME));
+ verify(spyPackageMonitor, times(1)).onPackageModifiedWithExtras(eq(FAKE_PACKAGE_NAME),
+ argumentCaptor.capture());
- ArgumentCaptor<Bundle> argumentCaptor = ArgumentCaptor.forClass(Bundle.class);
verify(spyPackageMonitor, times(1))
.onPackageDisappearedWithExtras(eq(FAKE_PACKAGE_NAME), argumentCaptor.capture());
Bundle capturedExtras = argumentCaptor.getValue();
@@ -389,12 +407,18 @@
spyPackageMonitor.doHandlePackageEvent(intent);
verify(spyPackageMonitor, times(1)).onBeginPackageChanges();
+ ArgumentCaptor<Bundle> argumentCaptor = ArgumentCaptor.forClass(Bundle.class);
verify(spyPackageMonitor, times(1))
.onPackageRemoved(eq(FAKE_PACKAGE_NAME), eq(FAKE_PACKAGE_UID));
verify(spyPackageMonitor, times(1))
+ .onPackageRemovedWithExtras(eq(FAKE_PACKAGE_NAME), eq(FAKE_PACKAGE_UID),
+ argumentCaptor.capture());
+ verify(spyPackageMonitor, times(1))
.onPackageRemovedAllUsers(eq(FAKE_PACKAGE_NAME), eq(FAKE_PACKAGE_UID));
+ verify(spyPackageMonitor, times(1))
+ .onPackageRemovedAllUsersWithExtras(eq(FAKE_PACKAGE_NAME), eq(FAKE_PACKAGE_UID),
+ argumentCaptor.capture());
- ArgumentCaptor<Bundle> argumentCaptor = ArgumentCaptor.forClass(Bundle.class);
verify(spyPackageMonitor, times(1)).onPackageDisappearedWithExtras(eq(FAKE_PACKAGE_NAME),
argumentCaptor.capture());
Bundle capturedExtras = argumentCaptor.getValue();
@@ -426,11 +450,16 @@
spyPackageMonitor.doHandlePackageEvent(intent);
verify(spyPackageMonitor, times(1)).onBeginPackageChanges();
+ ArgumentCaptor<Bundle> argumentCaptor = ArgumentCaptor.forClass(Bundle.class);
verify(spyPackageMonitor, times(1))
.onPackageUpdateFinished(eq(FAKE_PACKAGE_NAME), eq(FAKE_PACKAGE_UID));
+ verify(spyPackageMonitor, times(1))
+ .onPackageModifiedWithExtras(eq(FAKE_PACKAGE_NAME), argumentCaptor.capture());
verify(spyPackageMonitor, times(1)).onPackageModified(eq(FAKE_PACKAGE_NAME));
+ verify(spyPackageMonitor, times(1))
+ .onPackageModifiedWithExtras(eq(FAKE_PACKAGE_NAME), argumentCaptor.capture());
- ArgumentCaptor<Bundle> argumentCaptor = ArgumentCaptor.forClass(Bundle.class);
+
verify(spyPackageMonitor, times(1)).onPackageAppearedWithExtras(eq(FAKE_PACKAGE_NAME),
argumentCaptor.capture());
Bundle capturedExtras = argumentCaptor.getValue();
@@ -462,8 +491,11 @@
verify(spyPackageMonitor, times(1)).onBeginPackageChanges();
verify(spyPackageMonitor, times(1))
.onPackageAdded(eq(FAKE_PACKAGE_NAME), eq(FAKE_PACKAGE_UID));
-
ArgumentCaptor<Bundle> argumentCaptor = ArgumentCaptor.forClass(Bundle.class);
+ verify(spyPackageMonitor, times(1))
+ .onPackageAddedWithExtras(eq(FAKE_PACKAGE_NAME), eq(FAKE_PACKAGE_UID),
+ argumentCaptor.capture());
+
verify(spyPackageMonitor, times(1)).onPackageAppearedWithExtras(eq(FAKE_PACKAGE_NAME),
argumentCaptor.capture());
Bundle capturedExtras = argumentCaptor.getValue();
@@ -487,7 +519,7 @@
}
public TestPackageMonitor() {
- super();
+ super(false);
}
}
}
diff --git a/core/tests/utiltests/src/com/android/internal/util/ProcFileReaderTest.java b/core/tests/utiltests/src/com/android/internal/util/ProcFileReaderTest.java
index 4c00c16..9785ca7 100644
--- a/core/tests/utiltests/src/com/android/internal/util/ProcFileReaderTest.java
+++ b/core/tests/utiltests/src/com/android/internal/util/ProcFileReaderTest.java
@@ -216,6 +216,46 @@
}
@Test
+ public void testBufferSizeWithConsecutiveDelimiters() throws Exception {
+ // Read numbers using very small buffer size, exercising fillBuf()
+ // Include more consecutive delimiters than the buffer size.
+ final ProcFileReader reader =
+ buildReader("1 21 3 41 5 61 7 81 9 10\n", 3);
+
+ assertEquals(1, reader.nextInt());
+ assertEquals(21, reader.nextInt());
+ assertEquals(3, reader.nextInt());
+ assertEquals(41, reader.nextInt());
+ assertEquals(5, reader.nextInt());
+ assertEquals(61, reader.nextInt());
+ assertEquals(7, reader.nextInt());
+ assertEquals(81, reader.nextInt());
+ assertEquals(9, reader.nextInt());
+ assertEquals(10, reader.nextInt());
+ reader.finishLine();
+ assertFalse(reader.hasMoreData());
+ }
+
+ @Test
+ public void testBufferSizeWithConsecutiveDelimitersAndMultipleLines() throws Exception {
+ final ProcFileReader reader =
+ buildReader("1 21 41 \n 5 7 81 \n 9 10 \n", 3);
+
+ assertEquals(1, reader.nextInt());
+ assertEquals(21, reader.nextInt());
+ assertEquals(41, reader.nextInt());
+ reader.finishLine();
+ assertEquals(5, reader.nextInt());
+ assertEquals(7, reader.nextInt());
+ assertEquals(81, reader.nextInt());
+ reader.finishLine();
+ assertEquals(9, reader.nextInt());
+ assertEquals(10, reader.nextInt());
+ reader.finishLine();
+ assertFalse(reader.hasMoreData());
+ }
+
+ @Test
public void testIgnore() throws Exception {
final ProcFileReader reader = buildReader("a b c\n");
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index 9d1e507..65615e6 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -322,11 +322,11 @@
<library name="android.hidl.manager-V1.0-java"
file="/system/framework/android.hidl.manager-V1.0-java.jar" />
- <!-- These are the standard packages that are white-listed to always have internet
+ <!-- These are the standard packages that are allowed to always have internet
access while in power save mode, even if they aren't in the foreground. -->
<allow-in-power-save package="com.android.providers.downloads" />
- <!-- These are the standard packages that are white-listed to always have internet
+ <!-- These are the standard packages that are allowed to always have internet
access while in data mode, even if they aren't in the foreground. -->
<allow-in-data-usage-save package="com.android.providers.downloads" />
@@ -338,7 +338,7 @@
<!-- Emergency app needs to run in the background to reliably provide safety features -->
<allow-in-power-save package="com.android.emergency" />
- <!-- Whitelist system providers -->
+ <!-- Allow system providers -->
<!-- Calendar provider needs alarms while in idle -->
<allow-in-power-save package="com.android.providers.calendar" />
<allow-in-power-save-except-idle package="com.android.providers.contacts" />
diff --git a/data/keyboards/Android.bp b/data/keyboards/Android.bp
index f15c153..423b55b 100644
--- a/data/keyboards/Android.bp
+++ b/data/keyboards/Android.bp
@@ -27,3 +27,27 @@
targets: ["droidcore"],
},
}
+
+prebuilt_usr_keylayout {
+ name: "keylayout_data",
+ srcs: [
+ "*.kl",
+ ],
+ no_full_install: true,
+}
+
+prebuilt_usr_keychars {
+ name: "keychars_data",
+ srcs: [
+ "*.kcm",
+ ],
+ no_full_install: true,
+}
+
+prebuilt_usr_idc {
+ name: "idc_data",
+ srcs: [
+ "*.idc",
+ ],
+ no_full_install: true,
+}
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 319f115..6d31578 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -465,6 +465,11 @@
* how pixels are stored. This affects the quality (color depth) as
* well as the ability to display transparent/translucent colors.
*/
+ // It's touched by Graphics.cpp, so we need to make this enum usable on Ravenwood.
+ // Otherwise, all the ctors would throw, which would make the class unloadable
+ // because the static initializer needs the enum members because of `sConfigs`.
+ // TODO: Remove it once we expose the outer class.
+ @android.ravenwood.annotation.RavenwoodKeepWholeClass
public enum Config {
// these native values must match up with the enum in SkBitmap.h
diff --git a/graphics/java/android/graphics/FontFamily.java b/graphics/java/android/graphics/FontFamily.java
index f50de16..c86b744 100644
--- a/graphics/java/android/graphics/FontFamily.java
+++ b/graphics/java/android/graphics/FontFamily.java
@@ -45,15 +45,17 @@
private static String TAG = "FontFamily";
- private static final NativeAllocationRegistry sBuilderRegistry =
- NativeAllocationRegistry.createMalloced(
- FontFamily.class.getClassLoader(), nGetBuilderReleaseFunc());
-
private @Nullable Runnable mNativeBuilderCleaner;
- private static final NativeAllocationRegistry sFamilyRegistry =
- NativeAllocationRegistry.createMalloced(
- FontFamily.class.getClassLoader(), nGetFamilyReleaseFunc());
+ private static class NoImagePreloadHolder {
+ private static final NativeAllocationRegistry sBuilderRegistry =
+ NativeAllocationRegistry.createMalloced(
+ FontFamily.class.getClassLoader(), nGetBuilderReleaseFunc());
+
+ private static final NativeAllocationRegistry sFamilyRegistry =
+ NativeAllocationRegistry.createMalloced(
+ FontFamily.class.getClassLoader(), nGetFamilyReleaseFunc());
+ }
/**
* @hide
@@ -74,7 +76,8 @@
publicAlternatives = "Use {@link android.graphics.fonts.FontFamily} instead.")
public FontFamily() {
mBuilderPtr = nInitBuilder(null, 0);
- mNativeBuilderCleaner = sBuilderRegistry.registerNativeAllocation(this, mBuilderPtr);
+ mNativeBuilderCleaner = NoImagePreloadHolder.sBuilderRegistry.registerNativeAllocation(this,
+ mBuilderPtr);
}
/**
@@ -92,7 +95,8 @@
langsString = TextUtils.join(",", langs);
}
mBuilderPtr = nInitBuilder(langsString, variant);
- mNativeBuilderCleaner = sBuilderRegistry.registerNativeAllocation(this, mBuilderPtr);
+ mNativeBuilderCleaner = NoImagePreloadHolder.sBuilderRegistry.registerNativeAllocation(this,
+ mBuilderPtr);
}
/**
@@ -113,7 +117,7 @@
mNativeBuilderCleaner.run();
mBuilderPtr = 0;
if (mNativePtr != 0) {
- sFamilyRegistry.registerNativeAllocation(this, mNativePtr);
+ NoImagePreloadHolder.sFamilyRegistry.registerNativeAllocation(this, mNativePtr);
}
return mNativePtr != 0;
}
diff --git a/graphics/java/android/graphics/Interpolator.java b/graphics/java/android/graphics/Interpolator.java
index 1045464..994fb2d 100644
--- a/graphics/java/android/graphics/Interpolator.java
+++ b/graphics/java/android/graphics/Interpolator.java
@@ -18,6 +18,9 @@
import android.os.SystemClock;
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
+@android.ravenwood.annotation.RavenwoodClassLoadHook(
+ android.ravenwood.annotation.RavenwoodClassLoadHook.LIBANDROID_LOADING_HOOK)
public class Interpolator {
public Interpolator(int valueCount) {
diff --git a/graphics/java/android/graphics/Matrix.java b/graphics/java/android/graphics/Matrix.java
index bc58feb..fbb690c 100644
--- a/graphics/java/android/graphics/Matrix.java
+++ b/graphics/java/android/graphics/Matrix.java
@@ -28,6 +28,9 @@
/**
* The Matrix class holds a 3x3 matrix for transforming coordinates.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
+@android.ravenwood.annotation.RavenwoodClassLoadHook(
+ android.ravenwood.annotation.RavenwoodClassLoadHook.LIBANDROID_LOADING_HOOK)
public class Matrix {
public static final int MSCALE_X = 0; //!< use with getValues/setValues
@@ -229,7 +232,7 @@
private static class NoImagePreloadHolder {
public static final NativeAllocationRegistry sRegistry =
NativeAllocationRegistry.createMalloced(
- Matrix.class.getClassLoader(), nGetNativeFinalizer());
+ Matrix.class.getClassLoader(), nGetNativeFinalizerWrapper());
}
private final long native_instance;
@@ -238,7 +241,7 @@
* Create an identity matrix
*/
public Matrix() {
- native_instance = nCreate(0);
+ native_instance = nCreateWrapper(0);
NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, native_instance);
}
@@ -248,7 +251,7 @@
* @param src The matrix to copy into this matrix
*/
public Matrix(Matrix src) {
- native_instance = nCreate(src != null ? src.native_instance : 0);
+ native_instance = nCreateWrapper(src != null ? src.native_instance : 0);
NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, native_instance);
}
@@ -846,6 +849,34 @@
return native_instance;
}
+ /**
+ * Wrapper method we use to switch to ExtraNatives.nCreate(src) only on Ravenwood.
+ *
+ * @see ExtraNatives
+ */
+ @android.ravenwood.annotation.RavenwoodReplace
+ private static long nCreateWrapper(long src) {
+ return nCreate(src);
+ }
+
+ private static long nCreateWrapper$ravenwood(long src) {
+ return ExtraNatives.nCreate(src);
+ }
+
+ /**
+ * Wrapper method we use to switch to ExtraNatives.nGetNativeFinalizer(src) only on Ravenwood.
+ *
+ * @see ExtraNatives
+ */
+ @android.ravenwood.annotation.RavenwoodReplace
+ private static long nGetNativeFinalizerWrapper() {
+ return nGetNativeFinalizer();
+ }
+
+ private static long nGetNativeFinalizerWrapper$ravenwood() {
+ return ExtraNatives.nGetNativeFinalizer();
+ }
+
// ------------------ Regular JNI ------------------------
private static native long nCreate(long nSrc_or_zero);
@@ -943,4 +974,25 @@
private static native float nMapRadius(long nObject, float radius);
@CriticalNative
private static native boolean nEquals(long nA, long nB);
+
+ /**
+ * Due to b/337329128, native methods that are called by the static initializers cannot be
+ * in the same class when running on a host side JVM (such as on Ravenwood and Android Studio).
+ *
+ * There are two methods that are called by the static initializers (either directly or
+ * indirectly) in this class, namely nCreate() and nGetNativeFinalizer(). On Ravenwood
+ * these methods can't be on the Matrix class itself, so we use a nested class to host them.
+ *
+ * We still keep the original nCreate() method and call it on non-ravenwood environment,
+ * in order to avoid problems in downstream (such as Android Studio).
+ *
+ * @see #nCreateWrapper(long)
+ * @see #nGetNativeFinalizerWrapper()
+ *
+ * TODO(b/337110712) Clean it up somehow. (remove the original nCreate() and unify the code?)
+ */
+ private static class ExtraNatives {
+ static native long nCreate(long nSrc_or_zero);
+ static native long nGetNativeFinalizer();
+ }
}
diff --git a/graphics/java/android/graphics/Path.java b/graphics/java/android/graphics/Path.java
index deb89fa..073307c 100644
--- a/graphics/java/android/graphics/Path.java
+++ b/graphics/java/android/graphics/Path.java
@@ -36,11 +36,16 @@
* (based on the paint's Style), or it can be used for clipping or to draw
* text on a path.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
+@android.ravenwood.annotation.RavenwoodClassLoadHook(
+ android.ravenwood.annotation.RavenwoodClassLoadHook.LIBANDROID_LOADING_HOOK)
public class Path {
-
- private static final NativeAllocationRegistry sRegistry =
- NativeAllocationRegistry.createMalloced(
- Path.class.getClassLoader(), nGetFinalizer());
+ // See b/337329128 for why we need an inner class here.
+ private static class NoImagePreloadHolder {
+ static final NativeAllocationRegistry sRegistry =
+ NativeAllocationRegistry.createMalloced(
+ Path.class.getClassLoader(), nGetFinalizer());
+ }
/**
* @hide
@@ -52,7 +57,7 @@
*/
public Path() {
mNativePath = nInit();
- sRegistry.registerNativeAllocation(this, mNativePath);
+ NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, mNativePath);
}
/**
@@ -62,7 +67,7 @@
*/
public Path(@Nullable Path src) {
mNativePath = nInit(src != null ? src.mNativePath : 0);
- sRegistry.registerNativeAllocation(this, mNativePath);
+ NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, mNativePath);
}
/**
diff --git a/graphics/java/android/graphics/fonts/Font.java b/graphics/java/android/graphics/fonts/Font.java
index 28cc051..318aadd 100644
--- a/graphics/java/android/graphics/fonts/Font.java
+++ b/graphics/java/android/graphics/fonts/Font.java
@@ -61,13 +61,15 @@
private static final int STYLE_ITALIC = 1;
private static final int STYLE_NORMAL = 0;
- private static final NativeAllocationRegistry BUFFER_REGISTRY =
- NativeAllocationRegistry.createMalloced(
- ByteBuffer.class.getClassLoader(), nGetReleaseNativeFont());
+ private static class NoImagePreloadHolder {
+ private static final NativeAllocationRegistry BUFFER_REGISTRY =
+ NativeAllocationRegistry.createMalloced(
+ ByteBuffer.class.getClassLoader(), nGetReleaseNativeFont());
- private static final NativeAllocationRegistry FONT_REGISTRY =
- NativeAllocationRegistry.createMalloced(Font.class.getClassLoader(),
- nGetReleaseNativeFont());
+ private static final NativeAllocationRegistry FONT_REGISTRY =
+ NativeAllocationRegistry.createMalloced(Font.class.getClassLoader(),
+ nGetReleaseNativeFont());
+ }
/**
* A builder class for creating new Font.
@@ -530,7 +532,7 @@
public Font(long nativePtr) {
mNativePtr = nativePtr;
- FONT_REGISTRY.registerNativeAllocation(this, mNativePtr);
+ NoImagePreloadHolder.FONT_REGISTRY.registerNativeAllocation(this, mNativePtr);
}
/**
@@ -551,7 +553,7 @@
ByteBuffer fromNative = nNewByteBuffer(mNativePtr);
// Bind ByteBuffer's lifecycle with underlying font object.
- BUFFER_REGISTRY.registerNativeAllocation(fromNative, ref);
+ NoImagePreloadHolder.BUFFER_REGISTRY.registerNativeAllocation(fromNative, ref);
// JNI NewDirectBuffer creates writable ByteBuffer even if it is mmaped readonly.
mBuffer = fromNative.asReadOnlyBuffer();
diff --git a/graphics/java/android/graphics/fonts/FontFamily.java b/graphics/java/android/graphics/fonts/FontFamily.java
index 199e929..bd13276 100644
--- a/graphics/java/android/graphics/fonts/FontFamily.java
+++ b/graphics/java/android/graphics/fonts/FontFamily.java
@@ -73,9 +73,11 @@
* A builder class for creating new FontFamily.
*/
public static final class Builder {
- private static final NativeAllocationRegistry sFamilyRegistory =
- NativeAllocationRegistry.createMalloced(FontFamily.class.getClassLoader(),
- nGetReleaseNativeFamily());
+ private static class NoImagePreloadHolder {
+ private static final NativeAllocationRegistry sFamilyRegistry =
+ NativeAllocationRegistry.createMalloced(FontFamily.class.getClassLoader(),
+ nGetReleaseNativeFamily());
+ }
private final ArrayList<Font> mFonts = new ArrayList<>();
// Most FontFamily only has regular, bold, italic, bold-italic. Thus 4 should be good for
@@ -183,7 +185,7 @@
final long ptr = nBuild(builderPtr, langTags, variant, isCustomFallback,
isDefaultFallback, variableFamilyType);
final FontFamily family = new FontFamily(ptr);
- sFamilyRegistory.registerNativeAllocation(family, ptr);
+ NoImagePreloadHolder.sFamilyRegistry.registerNativeAllocation(family, ptr);
return family;
}
diff --git a/graphics/java/android/graphics/text/LineBreaker.java b/graphics/java/android/graphics/text/LineBreaker.java
index 0e9f29d..0c6d4bd 100644
--- a/graphics/java/android/graphics/text/LineBreaker.java
+++ b/graphics/java/android/graphics/text/LineBreaker.java
@@ -480,9 +480,11 @@
}
}
- private static final NativeAllocationRegistry sRegistry =
- NativeAllocationRegistry.createMalloced(
- LineBreaker.class.getClassLoader(), nGetReleaseFunc());
+ private static class NoImagePreloadHolder {
+ private static final NativeAllocationRegistry sRegistry =
+ NativeAllocationRegistry.createMalloced(
+ LineBreaker.class.getClassLoader(), nGetReleaseFunc());
+ }
private final long mNativePtr;
@@ -494,7 +496,7 @@
@Nullable int[] indents, boolean useBoundsForWidth) {
mNativePtr = nInit(breakStrategy, hyphenationFrequency,
justify == JUSTIFICATION_MODE_INTER_WORD, indents, useBoundsForWidth);
- sRegistry.registerNativeAllocation(this, mNativePtr);
+ NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, mNativePtr);
}
/**
diff --git a/graphics/java/android/graphics/text/PositionedGlyphs.java b/graphics/java/android/graphics/text/PositionedGlyphs.java
index 7932e33..f8328b1 100644
--- a/graphics/java/android/graphics/text/PositionedGlyphs.java
+++ b/graphics/java/android/graphics/text/PositionedGlyphs.java
@@ -46,9 +46,11 @@
* @see TextRunShaper#shapeTextRun(CharSequence, int, int, int, int, float, float, boolean, Paint)
*/
public final class PositionedGlyphs {
- private static final NativeAllocationRegistry REGISTRY =
- NativeAllocationRegistry.createMalloced(
- Typeface.class.getClassLoader(), nReleaseFunc());
+ private static class NoImagePreloadHolder {
+ private static final NativeAllocationRegistry REGISTRY =
+ NativeAllocationRegistry.createMalloced(
+ Typeface.class.getClassLoader(), nReleaseFunc());
+ }
private final long mLayoutPtr;
private final float mXOffset;
@@ -259,7 +261,7 @@
mFonts.add(prevFont);
}
- REGISTRY.registerNativeAllocation(this, layoutPtr);
+ NoImagePreloadHolder.REGISTRY.registerNativeAllocation(this, layoutPtr);
}
@CriticalNative
diff --git a/keystore/java/android/security/keystore/KeyProperties.java b/keystore/java/android/security/keystore/KeyProperties.java
index 8c42547..7f936f2 100644
--- a/keystore/java/android/security/keystore/KeyProperties.java
+++ b/keystore/java/android/security/keystore/KeyProperties.java
@@ -22,7 +22,6 @@
import android.annotation.StringDef;
import android.annotation.SystemApi;
import android.os.Process;
-import android.security.KeyStore;
import android.security.keymaster.KeymasterDefs;
import libcore.util.EmptyArray;
@@ -1008,13 +1007,20 @@
public static final int NAMESPACE_LOCKSETTINGS = 103;
/**
+ * The legacy UID that corresponds to {@link #NAMESPACE_APPLICATION}.
+ * In new code, prefer to work with Keystore namespaces directly.
+ * @hide
+ */
+ public static final int UID_SELF = -1;
+
+ /**
* For legacy support, translate namespaces into known UIDs.
* @hide
*/
public static int namespaceToLegacyUid(@Namespace int namespace) {
switch (namespace) {
case NAMESPACE_APPLICATION:
- return KeyStore.UID_SELF;
+ return UID_SELF;
case NAMESPACE_WIFI:
return Process.WIFI_UID;
default:
@@ -1029,7 +1035,7 @@
*/
public static @Namespace int legacyUidToNamespace(int uid) {
switch (uid) {
- case KeyStore.UID_SELF:
+ case UID_SELF:
return NAMESPACE_APPLICATION;
case Process.WIFI_UID:
return NAMESPACE_WIFI;
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
index e38038e..14388a6 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
@@ -28,6 +28,7 @@
import static android.window.TaskFragmentOrganizer.KEY_ERROR_CALLBACK_TASK_FRAGMENT_INFO;
import static android.window.TaskFragmentOrganizer.KEY_ERROR_CALLBACK_THROWABLE;
import static android.window.TaskFragmentOrganizer.TASK_FRAGMENT_TRANSIT_CLOSE;
+import static android.window.TaskFragmentOrganizer.TASK_FRAGMENT_TRANSIT_DRAG_RESIZE;
import static android.window.TaskFragmentOrganizer.TASK_FRAGMENT_TRANSIT_OPEN;
import static android.window.TaskFragmentTransaction.TYPE_ACTIVITY_REPARENTED_TO_TASK;
import static android.window.TaskFragmentTransaction.TYPE_TASK_FRAGMENT_APPEARED;
@@ -850,6 +851,14 @@
Log.e(TAG, "onTaskFragmentParentInfoChanged on empty Task id=" + taskId);
return;
}
+
+ if (!parentInfo.isVisible()) {
+ // Only making the TaskContainer invisible and drops the other info, and perform the
+ // update when the next time the Task becomes visible.
+ taskContainer.setIsVisible(false);
+ return;
+ }
+
// Checks if container should be updated before apply new parentInfo.
final boolean shouldUpdateContainer = taskContainer.shouldUpdateContainer(parentInfo);
taskContainer.updateTaskFragmentParentInfo(parentInfo);
@@ -3137,11 +3146,9 @@
private static EmbeddedActivityWindowInfo translateActivityWindowInfo(
@NonNull Activity activity, @NonNull ActivityWindowInfo activityWindowInfo) {
final boolean isEmbedded = activityWindowInfo.isEmbedded();
- final Rect activityBounds = new Rect(activity.getResources().getConfiguration()
- .windowConfiguration.getBounds());
final Rect taskBounds = new Rect(activityWindowInfo.getTaskBounds());
final Rect activityStackBounds = new Rect(activityWindowInfo.getTaskFragmentBounds());
- return new EmbeddedActivityWindowInfo(activity, isEmbedded, activityBounds, taskBounds,
+ return new EmbeddedActivityWindowInfo(activity, isEmbedded, taskBounds,
activityStackBounds);
}
@@ -3245,6 +3252,7 @@
synchronized (mLock) {
final TransactionRecord transactionRecord =
mTransactionManager.startNewTransaction();
+ transactionRecord.setOriginType(TASK_FRAGMENT_TRANSIT_DRAG_RESIZE);
final WindowContainerTransaction wct = transactionRecord.getTransaction();
final TaskContainer taskContainer = mTaskContainers.get(taskId);
if (taskContainer != null) {
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
index 67d34c7..a683738 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
@@ -151,6 +151,10 @@
return mIsVisible;
}
+ void setIsVisible(boolean visible) {
+ mIsVisible = visible;
+ }
+
boolean hasDirectActivity() {
return mHasDirectActivity;
}
@@ -185,13 +189,15 @@
boolean shouldUpdateContainer(@NonNull TaskFragmentParentInfo info) {
final Configuration configuration = info.getConfiguration();
- return info.isVisible()
- // No need to update presentation in PIP until the Task exit PIP.
- && !isInPictureInPicture(configuration)
- // If the task properties equals regardless of starting position, don't need to
- // update the container.
- && (mConfiguration.diffPublicOnly(configuration) != 0
- || mDisplayId != info.getDisplayId());
+ if (isInPictureInPicture(configuration)) {
+ // No need to update presentation in PIP until the Task exit PIP.
+ return false;
+ }
+
+ // If the task properties equals regardless of starting position, don't
+ // need to update the container.
+ return mConfiguration.diffPublicOnly(configuration) != 0
+ || mDisplayId != info.getDisplayId();
}
/**
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java
index 4fd11c4..070fa5b 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java
@@ -45,6 +45,7 @@
import androidx.window.common.DeviceStateManagerFoldingFeatureProducer;
import androidx.window.common.EmptyLifecycleCallbacksAdapter;
import androidx.window.extensions.core.util.function.Consumer;
+import androidx.window.extensions.util.DeduplicateConsumer;
import java.util.ArrayList;
import java.util.Collections;
@@ -62,7 +63,7 @@
private final Object mLock = new Object();
@GuardedBy("mLock")
- private final Map<Context, Consumer<WindowLayoutInfo>> mWindowLayoutChangeListeners =
+ private final Map<Context, DeduplicateConsumer<WindowLayoutInfo>> mWindowLayoutChangeListeners =
new ArrayMap<>();
@GuardedBy("mLock")
@@ -130,7 +131,7 @@
if (mWindowLayoutChangeListeners.containsKey(context)
// In theory this method can be called on the same consumer with different
// context.
- || mWindowLayoutChangeListeners.containsValue(consumer)) {
+ || containsConsumer(consumer)) {
return;
}
if (!context.isUiContext()) {
@@ -141,7 +142,7 @@
WindowLayoutInfo newWindowLayout = getWindowLayoutInfo(context, features);
consumer.accept(newWindowLayout);
});
- mWindowLayoutChangeListeners.put(context, consumer);
+ mWindowLayoutChangeListeners.put(context, new DeduplicateConsumer<>(consumer));
final IBinder windowContextToken = context.getWindowContextToken();
if (windowContextToken != null) {
@@ -176,22 +177,38 @@
@Override
public void removeWindowLayoutInfoListener(@NonNull Consumer<WindowLayoutInfo> consumer) {
synchronized (mLock) {
+ DeduplicateConsumer<WindowLayoutInfo> consumerToRemove = null;
for (Context context : mWindowLayoutChangeListeners.keySet()) {
- if (!mWindowLayoutChangeListeners.get(context).equals(consumer)) {
+ final DeduplicateConsumer<WindowLayoutInfo> deduplicateConsumer =
+ mWindowLayoutChangeListeners.get(context);
+ if (!deduplicateConsumer.matchesConsumer(consumer)) {
continue;
}
final IBinder token = context.getWindowContextToken();
+ consumerToRemove = deduplicateConsumer;
if (token != null) {
context.unregisterComponentCallbacks(mConfigurationChangeListeners.get(token));
mConfigurationChangeListeners.remove(token);
}
break;
}
- mWindowLayoutChangeListeners.values().remove(consumer);
+ if (consumerToRemove != null) {
+ mWindowLayoutChangeListeners.values().remove(consumerToRemove);
+ }
}
}
@GuardedBy("mLock")
+ private boolean containsConsumer(@NonNull Consumer<WindowLayoutInfo> consumer) {
+ for (DeduplicateConsumer<WindowLayoutInfo> c : mWindowLayoutChangeListeners.values()) {
+ if (c.matchesConsumer(consumer)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @GuardedBy("mLock")
private void updateListenerRegistrations() {
ActivityThread currentThread = ActivityThread.currentActivityThread();
if (mJavaToExtConsumers.isEmpty()) {
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/util/DeduplicateConsumer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/util/DeduplicateConsumer.java
new file mode 100644
index 0000000..ee271aa5
--- /dev/null
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/util/DeduplicateConsumer.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package androidx.window.extensions.util;
+
+import androidx.annotation.GuardedBy;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.window.extensions.core.util.function.Consumer;
+
+/**
+ * A utility class that will not report a value if it is the same as the last reported value.
+ * @param <T> generic values to be reported.
+ */
+public class DeduplicateConsumer<T> implements Consumer<T> {
+
+ private final Object mLock = new Object();
+ @GuardedBy("mLock")
+ @Nullable
+ private T mLastReportedValue = null;
+ @NonNull
+ private final Consumer<T> mConsumer;
+
+ public DeduplicateConsumer(@NonNull Consumer<T> consumer) {
+ mConsumer = consumer;
+ }
+
+ /**
+ * Returns {@code true} if the given consumer matches this object or the wrapped
+ * {@link Consumer}, {@code false} otherwise
+ */
+ public boolean matchesConsumer(@NonNull Consumer<T> consumer) {
+ return consumer == this || mConsumer.equals(consumer);
+ }
+
+ /**
+ * Accepts a new value and relays it if it is different from
+ * the last reported value.
+ * @param value to report if different.
+ */
+ @Override
+ public void accept(@NonNull T value) {
+ synchronized (mLock) {
+ if (mLastReportedValue != null && mLastReportedValue.equals(value)) {
+ return;
+ }
+ mLastReportedValue = value;
+ }
+ mConsumer.accept(value);
+ }
+}
diff --git a/libs/WindowManager/Jetpack/tests/unittest/Android.bp b/libs/WindowManager/Jetpack/tests/unittest/Android.bp
index 4ddbd13..61ea51a 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/Android.bp
+++ b/libs/WindowManager/Jetpack/tests/unittest/Android.bp
@@ -23,6 +23,7 @@
android_test {
name: "WMJetpackUnitTests",
+ team: "trendy_team_windowing_sdk",
// To make the test run via TEST_MAPPING
test_suites: ["device-tests"],
@@ -32,6 +33,7 @@
static_libs: [
"androidx.window.extensions",
+ "androidx.window.extensions.core_core",
"junit",
"androidx.test.runner",
"androidx.test.rules",
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/OverlayPresentationTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/OverlayPresentationTest.java
index fab298d..049a9e2 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/OverlayPresentationTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/OverlayPresentationTest.java
@@ -580,7 +580,7 @@
final TaskContainer.TaskProperties taskProperties = taskContainer.getTaskProperties();
final TaskFragmentParentInfo parentInfo = new TaskFragmentParentInfo(
new Configuration(taskProperties.getConfiguration()), taskProperties.getDisplayId(),
- false /* visible */, false /* hasDirectActivity */, null /* decorSurface */);
+ true /* visible */, false /* hasDirectActivity */, null /* decorSurface */);
mSplitController.onTaskFragmentParentInfoChanged(mTransaction, TASK_ID, parentInfo);
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
index 8bc3a30..7d86ec2 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
@@ -1570,8 +1570,6 @@
mSetFlagRule.enableFlags(Flags.FLAG_ACTIVITY_WINDOW_INFO_FLAG);
final boolean isEmbedded = true;
- final Rect activityBounds = mActivity.getResources().getConfiguration().windowConfiguration
- .getBounds();
final Rect taskBounds = new Rect(0, 0, 1000, 2000);
final Rect activityStackBounds = new Rect(0, 0, 500, 2000);
doReturn(isEmbedded).when(mActivityWindowInfo).isEmbedded();
@@ -1579,7 +1577,7 @@
doReturn(activityStackBounds).when(mActivityWindowInfo).getTaskFragmentBounds();
final EmbeddedActivityWindowInfo expected = new EmbeddedActivityWindowInfo(mActivity,
- isEmbedded, activityBounds, taskBounds, activityStackBounds);
+ isEmbedded, taskBounds, activityStackBounds);
assertEquals(expected, mSplitController.getEmbeddedActivityWindowInfo(mActivity));
}
@@ -1621,6 +1619,48 @@
verify(mEmbeddedActivityWindowInfoCallback, never()).accept(any());
}
+ @Test
+ public void testTaskFragmentParentInfoChanged() {
+ // Making a split
+ final Activity secondaryActivity = createMockActivity();
+ addSplitTaskFragments(mActivity, secondaryActivity, false /* clearTop */);
+
+ // Updates the parent info.
+ final TaskContainer taskContainer = mSplitController.getTaskContainer(TASK_ID);
+ final Configuration configuration = new Configuration();
+ final TaskFragmentParentInfo originalInfo = new TaskFragmentParentInfo(configuration,
+ DEFAULT_DISPLAY, true /* visible */, false /* hasDirectActivity */,
+ null /* decorSurface */);
+ mSplitController.onTaskFragmentParentInfoChanged(mock(WindowContainerTransaction.class),
+ TASK_ID, originalInfo);
+ assertTrue(taskContainer.isVisible());
+
+ // Making a public configuration change while the Task is invisible.
+ configuration.densityDpi += 100;
+ final TaskFragmentParentInfo invisibleInfo = new TaskFragmentParentInfo(configuration,
+ DEFAULT_DISPLAY, false /* visible */, false /* hasDirectActivity */,
+ null /* decorSurface */);
+ mSplitController.onTaskFragmentParentInfoChanged(mock(WindowContainerTransaction.class),
+ TASK_ID, invisibleInfo);
+
+ // Ensure the TaskContainer is inivisible, but the configuration is not updated.
+ assertFalse(taskContainer.isVisible());
+ assertTrue(taskContainer.getTaskFragmentParentInfo().getConfiguration().diffPublicOnly(
+ configuration) > 0);
+
+ // Updates when Task to become visible
+ final TaskFragmentParentInfo visibleInfo = new TaskFragmentParentInfo(configuration,
+ DEFAULT_DISPLAY, true /* visible */, false /* hasDirectActivity */,
+ null /* decorSurface */);
+ mSplitController.onTaskFragmentParentInfoChanged(mock(WindowContainerTransaction.class),
+ TASK_ID, visibleInfo);
+
+ // Ensure the Task is visible and configuration is updated.
+ assertTrue(taskContainer.isVisible());
+ assertFalse(taskContainer.getTaskFragmentParentInfo().getConfiguration().diffPublicOnly(
+ configuration) > 0);
+ }
+
/** Creates a mock activity in the organizer process. */
private Activity createMockActivity() {
return createMockActivity(TASK_ID);
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/util/DeduplicateConsumerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/util/DeduplicateConsumerTest.java
new file mode 100644
index 0000000..4e9b4a0
--- /dev/null
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/util/DeduplicateConsumerTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package androidx.window.extensions.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import androidx.window.extensions.core.util.function.Consumer;
+
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A class to validate {@link DeduplicateConsumer}.
+ */
+public class DeduplicateConsumerTest {
+
+ @Test
+ public void test_duplicate_value_is_filtered() {
+ String value = "test_value";
+ List<String> expected = new ArrayList<>();
+ expected.add(value);
+ RecordingConsumer recordingConsumer = new RecordingConsumer();
+ DeduplicateConsumer<String> deduplicateConsumer =
+ new DeduplicateConsumer<>(recordingConsumer);
+
+ deduplicateConsumer.accept(value);
+ deduplicateConsumer.accept(value);
+
+ assertEquals(expected, recordingConsumer.getValues());
+ }
+
+ @Test
+ public void test_different_value_is_filtered() {
+ String value = "test_value";
+ String newValue = "test_value_new";
+ List<String> expected = new ArrayList<>();
+ expected.add(value);
+ expected.add(newValue);
+ RecordingConsumer recordingConsumer = new RecordingConsumer();
+ DeduplicateConsumer<String> deduplicateConsumer =
+ new DeduplicateConsumer<>(recordingConsumer);
+
+ deduplicateConsumer.accept(value);
+ deduplicateConsumer.accept(value);
+ deduplicateConsumer.accept(newValue);
+
+ assertEquals(expected, recordingConsumer.getValues());
+ }
+
+ @Test
+ public void test_match_against_consumer_property_returns_true() {
+ RecordingConsumer recordingConsumer = new RecordingConsumer();
+ DeduplicateConsumer<String> deduplicateConsumer =
+ new DeduplicateConsumer<>(recordingConsumer);
+
+ assertTrue(deduplicateConsumer.matchesConsumer(recordingConsumer));
+ }
+
+ @Test
+ public void test_match_against_self_returns_true() {
+ RecordingConsumer recordingConsumer = new RecordingConsumer();
+ DeduplicateConsumer<String> deduplicateConsumer =
+ new DeduplicateConsumer<>(recordingConsumer);
+
+ assertTrue(deduplicateConsumer.matchesConsumer(deduplicateConsumer));
+ }
+
+ private static final class RecordingConsumer implements Consumer<String> {
+
+ private final List<String> mValues = new ArrayList<>();
+
+ @Override
+ public void accept(String s) {
+ mValues.add(s);
+ }
+
+ public List<String> getValues() {
+ return mValues;
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/aconfig/multitasking.aconfig b/libs/WindowManager/Shell/aconfig/multitasking.aconfig
index 7ff204c..fe68123 100644
--- a/libs/WindowManager/Shell/aconfig/multitasking.aconfig
+++ b/libs/WindowManager/Shell/aconfig/multitasking.aconfig
@@ -64,3 +64,10 @@
description: "Enables long-press action for nav handle when a bubble is expanded"
bug: "324910035"
}
+
+flag {
+ name: "enable_optional_bubble_overflow"
+ namespace: "multitasking"
+ description: "Hides the bubble overflow if there aren't any overflowed bubbles"
+ bug: "334175587"
+}
diff --git a/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_maximize_menu.xml b/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_maximize_menu.xml
index 9f0a425..9599658 100644
--- a/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_maximize_menu.xml
+++ b/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_maximize_menu.xml
@@ -23,7 +23,8 @@
android:orientation="horizontal"
android:gravity="center"
android:padding="16dp"
- android:background="@drawable/desktop_mode_maximize_menu_background">
+ android:background="@drawable/desktop_mode_maximize_menu_background"
+ android:elevation="1dp">
<LinearLayout
android:layout_width="wrap_content"
@@ -37,7 +38,8 @@
android:background="@drawable/desktop_mode_maximize_menu_layout_background"
android:padding="4dp"
android:layout_marginRight="8dp"
- android:layout_marginBottom="4dp">
+ android:layout_marginBottom="4dp"
+ android:alpha="0">
<Button
android:id="@+id/maximize_menu_maximize_button"
style="?android:attr/buttonBarButtonStyle"
@@ -48,6 +50,7 @@
</FrameLayout>
<TextView
+ android:id="@+id/maximize_menu_maximize_window_text"
android:layout_width="94dp"
android:layout_height="18dp"
android:textSize="11sp"
@@ -55,7 +58,8 @@
android:gravity="center"
android:fontFamily="google-sans-text"
android:text="@string/desktop_mode_maximize_menu_maximize_text"
- android:textColor="?androidprv:attr/materialColorOnSurface"/>
+ android:textColor="?androidprv:attr/materialColorOnSurface"
+ android:alpha="0"/>
</LinearLayout>
<LinearLayout
@@ -69,7 +73,8 @@
android:orientation="horizontal"
android:padding="4dp"
android:background="@drawable/desktop_mode_maximize_menu_layout_background"
- android:layout_marginBottom="4dp">
+ android:layout_marginBottom="4dp"
+ android:alpha="0">
<Button
android:id="@+id/maximize_menu_snap_left_button"
style="?android:attr/buttonBarButtonStyle"
@@ -88,6 +93,7 @@
android:stateListAnimator="@null"/>
</LinearLayout>
<TextView
+ android:id="@+id/maximize_menu_snap_window_text"
android:layout_width="94dp"
android:layout_height="18dp"
android:textSize="11sp"
@@ -96,6 +102,8 @@
android:gravity="center"
android:fontFamily="google-sans-text"
android:text="@string/desktop_mode_maximize_menu_snap_text"
- android:textColor="?androidprv:attr/materialColorOnSurface"/>
+ android:textColor="?androidprv:attr/materialColorOnSurface"
+ android:alpha="0"/>
</LinearLayout>
-</LinearLayout>
\ No newline at end of file
+</LinearLayout>
+
diff --git a/libs/WindowManager/Shell/res/values-af/strings.xml b/libs/WindowManager/Shell/res/values-af/strings.xml
index b9ff5c6..1c8f5e6 100644
--- a/libs/WindowManager/Shell/res/values-af/strings.xml
+++ b/libs/WindowManager/Shell/res/values-af/strings.xml
@@ -53,7 +53,7 @@
<string name="accessibility_split_top" msgid="2789329702027147146">"Verdeel bo"</string>
<string name="accessibility_split_bottom" msgid="8694551025220868191">"Verdeel onder"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Gebruik eenhandmodus"</string>
- <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Swiep van die onderkant van die skerm af op of tik enige plek bo die program om uit te gaan"</string>
+ <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Swiep van die onderkant van die skerm af op of tik enige plek bo die app om uit te gaan"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Begin eenhandmodus"</string>
<string name="accessibility_action_stop_one_handed" msgid="1369940261782179442">"Verlaat eenhandmodus"</string>
<string name="bubbles_settings_button_description" msgid="1301286017420516912">"Instellings vir <xliff:g id="APP_NAME">%1$s</xliff:g>-borrels"</string>
diff --git a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
index 1fde4cf..3aecf5f 100644
--- a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
@@ -53,7 +53,7 @@
<string name="accessibility_split_top" msgid="2789329702027147146">"Diviser dans la partie supérieure"</string>
<string name="accessibility_split_bottom" msgid="8694551025220868191">"Diviser dans la partie inférieure"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Utiliser le mode Une main"</string>
- <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Pour quitter, balayez l\'écran du bas vers le haut, ou touchez n\'importe où sur l\'écran en haut de l\'application"</string>
+ <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Pour quitter, balayez l\'écran du bas vers le haut, ou touchez n\'importe où sur l\'écran en haut de l\'appli"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Démarrer le mode Une main"</string>
<string name="accessibility_action_stop_one_handed" msgid="1369940261782179442">"Quitter le mode Une main"</string>
<string name="bubbles_settings_button_description" msgid="1301286017420516912">"Paramètres pour les bulles de l\'application <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/libs/WindowManager/Shell/res/values-fr/strings.xml b/libs/WindowManager/Shell/res/values-fr/strings.xml
index e7233ae..4002e4d 100644
--- a/libs/WindowManager/Shell/res/values-fr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fr/strings.xml
@@ -52,7 +52,7 @@
<string name="accessibility_split_right" msgid="8441001008181296837">"Affichée à droite"</string>
<string name="accessibility_split_top" msgid="2789329702027147146">"Affichée en haut"</string>
<string name="accessibility_split_bottom" msgid="8694551025220868191">"Affichée en haut"</string>
- <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Utiliser le mode une main"</string>
+ <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Utilisation du mode une main"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Pour quitter, balayez l\'écran de bas en haut ou appuyez n\'importe où au-dessus de l\'application"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Démarrer le mode une main"</string>
<string name="accessibility_action_stop_one_handed" msgid="1369940261782179442">"Quitter le mode une main"</string>
diff --git a/libs/WindowManager/Shell/res/values-hr/strings.xml b/libs/WindowManager/Shell/res/values-hr/strings.xml
index fc39420..27d4cfc 100644
--- a/libs/WindowManager/Shell/res/values-hr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hr/strings.xml
@@ -52,7 +52,7 @@
<string name="accessibility_split_right" msgid="8441001008181296837">"Podijeli desno"</string>
<string name="accessibility_split_top" msgid="2789329702027147146">"Podijeli gore"</string>
<string name="accessibility_split_bottom" msgid="8694551025220868191">"Podijeli dolje"</string>
- <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Korištenje načina rada jednom rukom"</string>
+ <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Upotreba načina rada jednom rukom"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Za izlaz prijeđite prstom od dna zaslona prema gore ili dodirnite bio gdje iznad aplikacije"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Pokretanje načina rada jednom rukom"</string>
<string name="accessibility_action_stop_one_handed" msgid="1369940261782179442">"Izlaz iz načina rada jednom rukom"</string>
diff --git a/libs/WindowManager/Shell/res/values/dimen.xml b/libs/WindowManager/Shell/res/values/dimen.xml
index c2c90c8..f532f96 100644
--- a/libs/WindowManager/Shell/res/values/dimen.xml
+++ b/libs/WindowManager/Shell/res/values/dimen.xml
@@ -420,7 +420,7 @@
<dimen name="freeform_decor_caption_height">42dp</dimen>
<!-- Height of desktop mode caption for freeform tasks. -->
- <dimen name="desktop_mode_freeform_decor_caption_height">42dp</dimen>
+ <dimen name="desktop_mode_freeform_decor_caption_height">40dp</dimen>
<!-- Height of desktop mode caption for fullscreen tasks. -->
<dimen name="desktop_mode_fullscreen_decor_caption_height">36dp</dimen>
@@ -464,6 +464,9 @@
<!-- The height of the maximize menu in desktop mode. -->
<dimen name="desktop_mode_maximize_menu_height">114dp</dimen>
+ <!-- The padding of the maximize menu in desktop mode. -->
+ <dimen name="desktop_mode_menu_padding">16dp</dimen>
+
<!-- The height of the buttons in the maximize menu. -->
<dimen name="desktop_mode_maximize_menu_button_height">52dp</dimen>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java
index d44033c..a426b20 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java
@@ -26,6 +26,7 @@
import static com.android.wm.shell.transition.TransitionAnimationHelper.addBackgroundToTransition;
import static com.android.wm.shell.transition.TransitionAnimationHelper.edgeExtendWindow;
import static com.android.wm.shell.transition.TransitionAnimationHelper.getTransitionBackgroundColorIfSet;
+import static com.android.wm.shell.transition.Transitions.TRANSIT_TASK_FRAGMENT_DRAG_RESIZE;
import android.animation.Animator;
import android.animation.ValueAnimator;
@@ -190,6 +191,10 @@
@NonNull
private List<ActivityEmbeddingAnimationAdapter> createAnimationAdapters(
@NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction startTransaction) {
+ if (info.getType() == TRANSIT_TASK_FRAGMENT_DRAG_RESIZE) {
+ // Jump cut for AE drag resizing because the content is veiled.
+ return new ArrayList<>();
+ }
boolean isChangeTransition = false;
for (TransitionInfo.Change change : info.getChanges()) {
if (change.hasFlags(FLAG_IS_BEHIND_STARTING_WINDOW)) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingController.java
index 1f9358e..d6b9d34 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingController.java
@@ -22,6 +22,7 @@
import static android.window.TransitionInfo.FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY;
import static com.android.wm.shell.transition.DefaultTransitionHandler.isSupportedOverrideAnimation;
+import static com.android.wm.shell.transition.Transitions.TRANSIT_TASK_FRAGMENT_DRAG_RESIZE;
import static java.util.Objects.requireNonNull;
@@ -90,6 +91,12 @@
/** Whether ActivityEmbeddingController should animate this transition. */
public boolean shouldAnimate(@NonNull TransitionInfo info) {
+ if (info.getType() == TRANSIT_TASK_FRAGMENT_DRAG_RESIZE) {
+ // The TRANSIT_TASK_FRAGMENT_DRAG_RESIZE type happens when the user drags the
+ // interactive divider to resize the split containers. The content is veiled, so we will
+ // handle the transition with a jump cut.
+ return true;
+ }
boolean containsEmbeddingChange = false;
for (TransitionInfo.Change change : info.getChanges()) {
if (!change.hasFlags(FLAG_FILLS_TASK) && change.hasFlags(
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
index edd5935..87aac0b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
@@ -1162,12 +1162,29 @@
}
/**
- * Update expanded state when a single bubble is dragged in Launcher.
+ * A bubble is being dragged in Launcher.
* Will be called only when bubble bar is expanded.
- * @param bubbleKey key of the bubble to collapse/expand
- * @param isBeingDragged whether the bubble is being dragged
+ *
+ * @param bubbleKey key of the bubble being dragged
*/
- public void onBubbleDrag(String bubbleKey, boolean isBeingDragged) {
+ public void startBubbleDrag(String bubbleKey) {
+ onBubbleDrag(bubbleKey, true /* isBeingDragged */);
+ }
+
+ /**
+ * A bubble is no longer being dragged in Launcher. As was released in given location.
+ * Will be called only when bubble bar is expanded.
+ *
+ * @param bubbleKey key of the bubble being dragged
+ * @param location location where bubble was released
+ */
+ public void stopBubbleDrag(String bubbleKey, BubbleBarLocation location) {
+ mBubblePositioner.setBubbleBarLocation(location);
+ onBubbleDrag(bubbleKey, false /* isBeingDragged */);
+ }
+
+ private void onBubbleDrag(String bubbleKey, boolean isBeingDragged) {
+ // TODO(b/330585402): collapse stack if any bubble is dragged
if (mBubbleData.getSelectedBubble() != null
&& mBubbleData.getSelectedBubble().getKey().equals(bubbleKey)) {
// Should collapse/expand only if equals to selected bubble.
@@ -1351,28 +1368,32 @@
}
String appBubbleKey = Bubble.getAppBubbleKeyForApp(intent.getPackage(), user);
- Log.i(TAG, "showOrHideAppBubble, key= " + appBubbleKey + " stackVisibility= "
- + (mStackView != null ? mStackView.getVisibility() : " null ")
- + " statusBarShade=" + mIsStatusBarShade);
PackageManager packageManager = getPackageManagerForUser(mContext, user.getIdentifier());
- if (!isResizableActivity(intent, packageManager, appBubbleKey)) return;
+ if (!isResizableActivity(intent, packageManager, appBubbleKey)) return; // logs errors
Bubble existingAppBubble = mBubbleData.getBubbleInStackWithKey(appBubbleKey);
+ ProtoLog.d(WM_SHELL_BUBBLES,
+ "showOrHideAppBubble, key=%s existingAppBubble=%s stackVisibility=%s "
+ + "statusBarShade=%s",
+ appBubbleKey, existingAppBubble,
+ (mStackView != null ? mStackView.getVisibility() : "null"),
+ mIsStatusBarShade);
+
if (existingAppBubble != null) {
BubbleViewProvider selectedBubble = mBubbleData.getSelectedBubble();
if (isStackExpanded()) {
if (selectedBubble != null && appBubbleKey.equals(selectedBubble.getKey())) {
+ ProtoLog.d(WM_SHELL_BUBBLES, "collapseStack for %s", appBubbleKey);
// App bubble is expanded, lets collapse
- Log.i(TAG, " showOrHideAppBubble, selected bubble is app bubble, collapsing");
collapseStack();
} else {
+ ProtoLog.d(WM_SHELL_BUBBLES, "setSelected for %s", appBubbleKey);
// App bubble is not selected, select it
- Log.i(TAG, " showOrHideAppBubble, expanded, selecting existing app bubble");
mBubbleData.setSelectedBubble(existingAppBubble);
}
} else {
+ ProtoLog.d(WM_SHELL_BUBBLES, "setSelectedBubbleAndExpandStack %s", appBubbleKey);
// App bubble is not selected, select it & expand
- Log.i(TAG, " showOrHideAppBubble, expand and select existing app bubble");
mBubbleData.setSelectedBubbleAndExpandStack(existingAppBubble);
}
} else {
@@ -1380,13 +1401,12 @@
Bubble b = mBubbleData.getOverflowBubbleWithKey(appBubbleKey);
if (b != null) {
// It's in the overflow, so remove it & reinflate
- Log.i(TAG, " showOrHideAppBubble, expanding app bubble from overflow");
mBubbleData.removeOverflowBubble(b);
} else {
// App bubble does not exist, lets add and expand it
- Log.i(TAG, " showOrHideAppBubble, creating and expanding app bubble");
b = Bubble.createAppBubble(intent, user, icon, mMainExecutor);
}
+ ProtoLog.d(WM_SHELL_BUBBLES, "inflateAndAdd %s", appBubbleKey);
b.setShouldAutoExpand(true);
inflateAndAdd(b, /* suppressFlyout= */ true, /* showInShade= */ false);
}
@@ -2329,8 +2349,13 @@
}
@Override
- public void onBubbleDrag(String bubbleKey, boolean isBeingDragged) {
- mMainExecutor.execute(() -> mController.onBubbleDrag(bubbleKey, isBeingDragged));
+ public void startBubbleDrag(String bubbleKey) {
+ mMainExecutor.execute(() -> mController.startBubbleDrag(bubbleKey));
+ }
+
+ @Override
+ public void stopBubbleDrag(String bubbleKey, BubbleBarLocation location) {
+ mMainExecutor.execute(() -> mController.stopBubbleDrag(bubbleKey, location));
}
@Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
index 14c3a070..c4bbe32 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
@@ -76,6 +76,7 @@
private int mBubblePaddingTop;
private int mBubbleOffscreenAmount;
private int mStackOffset;
+ private int mBubbleElevation;
private int mExpandedViewMinHeight;
private int mExpandedViewLargeScreenWidth;
@@ -147,6 +148,7 @@
mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top);
mBubbleOffscreenAmount = res.getDimensionPixelSize(R.dimen.bubble_stack_offscreen);
mStackOffset = res.getDimensionPixelSize(R.dimen.bubble_stack_offset);
+ mBubbleElevation = res.getDimensionPixelSize(R.dimen.bubble_elevation);
if (mShowingInBubbleBar) {
mExpandedViewLargeScreenWidth = Math.min(
@@ -662,6 +664,29 @@
}
/**
+ * Returns the z translation a specific bubble should use. When expanded we keep a slight
+ * translation to ensure proper ordering when animating to / from collapsed state. When
+ * collapsed, only the top two bubbles appear so only their shadows show.
+ */
+ public float getZTranslation(int index, boolean isOverflow, boolean isExpanded) {
+ if (isOverflow) {
+ return 0f; // overflow is lowest
+ }
+ return isExpanded
+ // When expanded use minimal amount to keep order
+ ? getMaxBubbles() - index
+ // When collapsed, only the top two bubbles have elevation
+ : index < NUM_VISIBLE_WHEN_RESTING
+ ? (getMaxBubbles() * mBubbleElevation) - index
+ : 0;
+ }
+
+ /** The elevation to use for bubble UI elements. */
+ public int getBubbleElevation() {
+ return mBubbleElevation;
+ }
+
+ /**
* @return whether the stack is considered on the left side of the screen.
*/
public boolean isStackOnLeft(PointF currentStackPosition) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
index dcc536b..3c788b1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
@@ -670,7 +670,7 @@
// First, see if the magnetized object consumes the event - if so, we shouldn't move the
// bubble since it's stuck to the target.
if (!passEventToMagnetizedObject(ev)) {
- updateBubbleShadows(true /* showForAllBubbles */);
+ updateBubbleShadows(true /* isExpanded */);
if (mBubbleData.isExpanded()) {
mExpandedAnimationController.dragBubbleOut(
v, viewInitialX + dx, viewInitialY + dy);
@@ -720,6 +720,7 @@
}
mIsDraggingStack = false;
+ mMagnetizedObject = null;
// Hide the stack after a delay, if needed.
updateTemporarilyInvisibleAnimation(false /* hideImmediately */);
@@ -890,18 +891,17 @@
mMainExecutor = mainExecutor;
mManager = bubbleStackViewManager;
+ mPositioner = bubblePositioner;
mBubbleData = data;
mSysuiProxyProvider = sysuiProxyProvider;
Resources res = getResources();
mBubbleSize = res.getDimensionPixelSize(R.dimen.bubble_size);
- mBubbleElevation = res.getDimensionPixelSize(R.dimen.bubble_elevation);
+ mBubbleElevation = mPositioner.getBubbleElevation();
mBubbleTouchPadding = res.getDimensionPixelSize(R.dimen.bubble_touch_padding);
mExpandedViewPadding = res.getDimensionPixelSize(R.dimen.bubble_expanded_view_padding);
- int elevation = res.getDimensionPixelSize(R.dimen.bubble_elevation);
- mPositioner = bubblePositioner;
final TypedArray ta = mContext.obtainStyledAttributes(
new int[]{android.R.attr.dialogCornerRadius});
@@ -934,12 +934,12 @@
mBubbleContainer = new PhysicsAnimationLayout(context);
mBubbleContainer.setActiveController(mStackAnimationController);
- mBubbleContainer.setElevation(elevation);
+ mBubbleContainer.setElevation(mBubbleElevation);
mBubbleContainer.setClipChildren(false);
addView(mBubbleContainer, new FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT));
mExpandedViewContainer = new FrameLayout(context);
- mExpandedViewContainer.setElevation(elevation);
+ mExpandedViewContainer.setElevation(mBubbleElevation);
mExpandedViewContainer.setClipChildren(false);
addView(mExpandedViewContainer);
@@ -1861,7 +1861,7 @@
bubble.getIconView().setDotBadgeOnLeft(!mStackOnLeftOrWillBe /* onLeft */);
bubble.getIconView().setOnClickListener(mBubbleClickListener);
bubble.getIconView().setOnTouchListener(mBubbleTouchListener);
- updateBubbleShadows(false /* showForAllBubbles */);
+ updateBubbleShadows(mIsExpanded);
animateInFlyoutForBubble(bubble);
requestUpdate();
logBubbleEvent(bubble, FrameworkStatsLog.BUBBLE_UICHANGED__ACTION__POSTED);
@@ -1964,7 +1964,7 @@
if (mIsExpanded || isExpansionAnimating()) {
reorder.run();
updateBadges(false /* setBadgeForCollapsedStack */);
- updateZOrder();
+ updateBubbleShadows(true /* isExpanded */);
} else {
List<View> bubbleViews = bubbles.stream()
.map(b -> b.getIconView()).collect(Collectors.toList());
@@ -2207,7 +2207,7 @@
mBubbleContainer.addView(bubble.getIconView(), index,
new LayoutParams(mPositioner.getBubbleSize(),
mPositioner.getBubbleSize()));
- updateBubbleShadows(false /* showForAllBubbles */);
+ updateBubbleShadows(mIsExpanded);
requestUpdate();
}
}
@@ -2340,7 +2340,7 @@
beforeExpandedViewAnimation();
showScrim(true, null /* runnable */);
- updateZOrder();
+ updateBubbleShadows(mIsExpanded);
updateBadges(false /* setBadgeForCollapsedStack */);
mBubbleContainer.setActiveController(mExpandedAnimationController);
updateOverflowVisibility();
@@ -2493,6 +2493,7 @@
() -> {
mBubbleContainer.setActiveController(mStackAnimationController);
updateOverflowVisibility();
+ animateShadows();
});
final Runnable after = () -> {
@@ -2503,7 +2504,6 @@
mManageEduView.hide();
}
- updateZOrder();
updateBadges(true /* setBadgeForCollapsedStack */);
afterExpandedViewAnimation();
if (previouslySelected != null) {
@@ -3338,19 +3338,23 @@
* Updates whether each of the bubbles should show shadows. When collapsed & resting, only the
* visible bubbles (top 2) will show a shadow. When the stack is being dragged, everything
* shows a shadow. When an individual bubble is dragged out, it should show a shadow.
+ * The bubble overflow is a special case and never has a shadow as it's ordered below the
+ * rest of the bubbles and isn't visible unless the stack is expanded.
+ *
+ * @param isExpanded whether the stack will be expanded or not when the shadows are applied.
*/
- private void updateBubbleShadows(boolean showForAllBubbles) {
- int bubbleCount = getBubbleCount();
- for (int i = 0; i < bubbleCount; i++) {
- final float z = (mPositioner.getMaxBubbles() * mBubbleElevation) - i;
- BadgedImageView bv = (BadgedImageView) mBubbleContainer.getChildAt(i);
- boolean isDraggedOut = mMagnetizedObject != null
+ private void updateBubbleShadows(boolean isExpanded) {
+ final int childCount = mBubbleContainer.getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ final BadgedImageView bv = (BadgedImageView) mBubbleContainer.getChildAt(i);
+ final boolean isOverflow = BubbleOverflow.KEY.equals(bv.getKey());
+ final boolean isDraggedOut = mMagnetizedObject != null
&& mMagnetizedObject.getUnderlyingObject().equals(bv);
- if (showForAllBubbles || isDraggedOut) {
- bv.setZ(z);
+ if (isDraggedOut) {
+ // If it's dragged out, it's above all the other bubbles
+ bv.setZ((mPositioner.getMaxBubbles() * mBubbleElevation) + 1);
} else {
- final float tz = i < NUM_VISIBLE_WHEN_RESTING ? z : 0f;
- bv.setZ(tz);
+ bv.setZ(mPositioner.getZTranslation(i, isOverflow, isExpanded));
}
}
}
@@ -3371,16 +3375,6 @@
}
}
- private void updateZOrder() {
- int bubbleCount = getBubbleCount();
- for (int i = 0; i < bubbleCount; i++) {
- BadgedImageView bv = (BadgedImageView) mBubbleContainer.getChildAt(i);
- bv.setZ(i < NUM_VISIBLE_WHEN_RESTING
- ? (mPositioner.getMaxBubbles() * mBubbleElevation) - i
- : 0f);
- }
- }
-
private void updateBadges(boolean setBadgeForCollapsedStack) {
int bubbleCount = getBubbleCount();
for (int i = 0; i < bubbleCount; i++) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/IBubbles.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/IBubbles.aidl
index c9f0f0d..66f77fa 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/IBubbles.aidl
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/IBubbles.aidl
@@ -39,11 +39,13 @@
oneway void collapseBubbles() = 6;
- oneway void onBubbleDrag(in String key, in boolean isBeingDragged) = 7;
+ oneway void startBubbleDrag(in String key) = 7;
oneway void showUserEducation(in int positionX, in int positionY) = 8;
oneway void setBubbleBarLocation(in BubbleBarLocation location) = 9;
oneway void setBubbleBarBounds(in Rect bubbleBarBounds) = 10;
+
+ oneway void stopBubbleDrag(in String key, in BubbleBarLocation location) = 11;
}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java
index 9440e98..f925eae 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java
@@ -356,7 +356,6 @@
MagnetizedObject.MagnetListener listener) {
mLayout.cancelAnimationsOnView(bubble);
- bubble.setTranslationZ(Short.MAX_VALUE);
mMagnetizedBubbleDraggingOut = new MagnetizedObject<View>(
mLayout.getContext(), bubble,
DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y) {
@@ -460,6 +459,7 @@
/**
* Snaps a bubble back to its position within the bubble row, and animates the rest of the
* bubbles to accommodate it if it was previously dragged out past the threshold.
+ * Only happens while the stack is expanded.
*/
public void snapBubbleBack(View bubbleView, float velX, float velY) {
if (mLayout == null) {
@@ -467,8 +467,12 @@
}
final int index = mLayout.indexOfChild(bubbleView);
final PointF p = mPositioner.getExpandedBubbleXY(index, mBubbleStackView.getState());
+ // overflow is not draggable so it's never the overflow
+ final float zTranslation = mPositioner.getZTranslation(index,
+ false /* isOverflow */,
+ true /* isExpanded */);
animationForChildAtIndex(index)
- .position(p.x, p.y, /* translationZ= */ 0f)
+ .position(p.x, p.y, zTranslation)
.withPositionStartVelocities(velX, velY)
.start();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
index a87116e..607a3b5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
@@ -185,7 +185,7 @@
nextTarget = snapAlgorithm.getDismissStartTarget();
}
if (nextTarget != null) {
- mSplitLayout.snapToTarget(mSplitLayout.getDividePosition(), nextTarget);
+ mSplitLayout.snapToTarget(mSplitLayout.getDividerPosition(), nextTarget);
return true;
}
return super.performAccessibilityAction(host, action, args);
@@ -345,9 +345,9 @@
mMoving = true;
}
if (mMoving) {
- final int position = mSplitLayout.getDividePosition() + touchPos - mStartPos;
+ final int position = mSplitLayout.getDividerPosition() + touchPos - mStartPos;
mLastDraggingPosition = position;
- mSplitLayout.updateDivideBounds(position);
+ mSplitLayout.updateDividerBounds(position);
}
break;
case MotionEvent.ACTION_UP:
@@ -363,7 +363,7 @@
final float velocity = isLeftRightSplit
? mVelocityTracker.getXVelocity()
: mVelocityTracker.getYVelocity();
- final int position = mSplitLayout.getDividePosition() + touchPos - mStartPos;
+ final int position = mSplitLayout.getDividerPosition() + touchPos - mStartPos;
final DividerSnapAlgorithm.SnapTarget snapTarget =
mSplitLayout.findSnapTarget(position, velocity, false /* hardDismiss */);
mSplitLayout.snapToTarget(position, snapTarget);
@@ -472,12 +472,12 @@
mInteractive = interactive;
mHideHandle = hideHandle;
if (!mInteractive && mHideHandle && mMoving) {
- final int position = mSplitLayout.getDividePosition();
- mSplitLayout.flingDividePosition(
+ final int position = mSplitLayout.getDividerPosition();
+ mSplitLayout.flingDividerPosition(
mLastDraggingPosition,
position,
mSplitLayout.FLING_RESIZE_DURATION,
- () -> mSplitLayout.setDividePosition(position, true /* applyLayoutChange */));
+ () -> mSplitLayout.setDividerPosition(position, true /* applyLayoutChange */));
mMoving = false;
}
releaseTouching();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
index 6b2d544..2ea32f4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
@@ -78,7 +78,7 @@
/**
* Records and handles layout of splits. Helps to calculate proper bounds when configuration or
- * divide position changes.
+ * divider position changes.
*/
public final class SplitLayout implements DisplayInsetsController.OnInsetsChangedListener {
private static final String TAG = "SplitLayout";
@@ -278,7 +278,7 @@
return mSplitWindowManager == null ? null : mSplitWindowManager.getSurfaceControl();
}
- int getDividePosition() {
+ int getDividerPosition() {
return mDividerPosition;
}
@@ -489,20 +489,20 @@
public void setDividerAtBorder(boolean start) {
final int pos = start ? mDividerSnapAlgorithm.getDismissStartTarget().position
: mDividerSnapAlgorithm.getDismissEndTarget().position;
- setDividePosition(pos, false /* applyLayoutChange */);
+ setDividerPosition(pos, false /* applyLayoutChange */);
}
/**
* Updates bounds with the passing position. Usually used to update recording bounds while
* performing animation or dragging divider bar to resize the splits.
*/
- void updateDivideBounds(int position) {
+ void updateDividerBounds(int position) {
updateBounds(position);
mSplitLayoutHandler.onLayoutSizeChanging(this, mSurfaceEffectPolicy.mParallaxOffset.x,
mSurfaceEffectPolicy.mParallaxOffset.y);
}
- void setDividePosition(int position, boolean applyLayoutChange) {
+ void setDividerPosition(int position, boolean applyLayoutChange) {
mDividerPosition = position;
updateBounds(mDividerPosition);
if (applyLayoutChange) {
@@ -511,14 +511,14 @@
}
/**
- * Updates divide position and split bounds base on the ratio within root bounds. Falls back
+ * Updates divider position and split bounds base on the ratio within root bounds. Falls back
* to middle position if the provided SnapTarget is not supported.
*/
public void setDivideRatio(@PersistentSnapPosition int snapPosition) {
final DividerSnapAlgorithm.SnapTarget snapTarget = mDividerSnapAlgorithm.findSnapTarget(
snapPosition);
- setDividePosition(snapTarget != null
+ setDividerPosition(snapTarget != null
? snapTarget.position
: mDividerSnapAlgorithm.getMiddleTarget().position,
false /* applyLayoutChange */);
@@ -546,24 +546,24 @@
}
/**
- * Sets new divide position and updates bounds correspondingly. Notifies listener if the new
+ * Sets new divider position and updates bounds correspondingly. Notifies listener if the new
* target indicates dismissing split.
*/
public void snapToTarget(int currentPosition, DividerSnapAlgorithm.SnapTarget snapTarget) {
switch (snapTarget.snapPosition) {
case SNAP_TO_START_AND_DISMISS:
- flingDividePosition(currentPosition, snapTarget.position, FLING_RESIZE_DURATION,
+ flingDividerPosition(currentPosition, snapTarget.position, FLING_RESIZE_DURATION,
() -> mSplitLayoutHandler.onSnappedToDismiss(false /* bottomOrRight */,
EXIT_REASON_DRAG_DIVIDER));
break;
case SNAP_TO_END_AND_DISMISS:
- flingDividePosition(currentPosition, snapTarget.position, FLING_RESIZE_DURATION,
+ flingDividerPosition(currentPosition, snapTarget.position, FLING_RESIZE_DURATION,
() -> mSplitLayoutHandler.onSnappedToDismiss(true /* bottomOrRight */,
EXIT_REASON_DRAG_DIVIDER));
break;
default:
- flingDividePosition(currentPosition, snapTarget.position, FLING_RESIZE_DURATION,
- () -> setDividePosition(snapTarget.position, true /* applyLayoutChange */));
+ flingDividerPosition(currentPosition, snapTarget.position, FLING_RESIZE_DURATION,
+ () -> setDividerPosition(snapTarget.position, true /* applyLayoutChange */));
break;
}
}
@@ -615,19 +615,19 @@
public void flingDividerToDismiss(boolean toEnd, int reason) {
final int target = toEnd ? mDividerSnapAlgorithm.getDismissEndTarget().position
: mDividerSnapAlgorithm.getDismissStartTarget().position;
- flingDividePosition(getDividePosition(), target, FLING_EXIT_DURATION,
+ flingDividerPosition(getDividerPosition(), target, FLING_EXIT_DURATION,
() -> mSplitLayoutHandler.onSnappedToDismiss(toEnd, reason));
}
/** Fling divider from current position to center position. */
public void flingDividerToCenter() {
final int pos = mDividerSnapAlgorithm.getMiddleTarget().position;
- flingDividePosition(getDividePosition(), pos, FLING_ENTER_DURATION,
- () -> setDividePosition(pos, true /* applyLayoutChange */));
+ flingDividerPosition(getDividerPosition(), pos, FLING_ENTER_DURATION,
+ () -> setDividerPosition(pos, true /* applyLayoutChange */));
}
@VisibleForTesting
- void flingDividePosition(int from, int to, int duration,
+ void flingDividerPosition(int from, int to, int duration,
@Nullable Runnable flingFinishedCallback) {
if (from == to) {
if (flingFinishedCallback != null) {
@@ -647,7 +647,7 @@
.setDuration(duration);
mDividerFlingAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
mDividerFlingAnimator.addUpdateListener(
- animation -> updateDivideBounds((int) animation.getAnimatedValue()));
+ animation -> updateDividerBounds((int) animation.getAnimatedValue()));
mDividerFlingAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIConfiguration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIConfiguration.java
index cf3ad42..713d04bc 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIConfiguration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIConfiguration.java
@@ -194,6 +194,10 @@
return mHideSizeCompatRestartButtonTolerance;
}
+ int getDefaultHideRestartButtonTolerance() {
+ return MAX_PERCENTAGE_VAL;
+ }
+
boolean getHasSeenLetterboxEducation(int userId) {
return mLetterboxEduSharedPreferences
.getBoolean(dontShowLetterboxEduKey(userId), /* default= */ false);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManager.java
index 4e5c2fa..f195f95 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManager.java
@@ -20,11 +20,11 @@
import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN;
import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED;
import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED;
+import static android.view.WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP;
import static android.window.TaskConstants.TASK_CHILD_LAYER_COMPAT_UI;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.app.AppCompatTaskInfo;
import android.app.CameraCompatTaskInfo.CameraCompatControlState;
import android.app.TaskInfo;
import android.content.Context;
@@ -219,14 +219,30 @@
@VisibleForTesting
boolean shouldShowSizeCompatRestartButton(@NonNull TaskInfo taskInfo) {
- if (!Flags.allowHideScmButton()) {
+ // Always show button if display is phone sized.
+ if (!Flags.allowHideScmButton() || taskInfo.configuration.smallestScreenWidthDp
+ < LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP) {
return true;
}
- final AppCompatTaskInfo appCompatTaskInfo = taskInfo.appCompatTaskInfo;
- final Rect taskBounds = taskInfo.configuration.windowConfiguration.getBounds();
- final int letterboxArea = computeArea(appCompatTaskInfo.topActivityLetterboxWidth,
- appCompatTaskInfo.topActivityLetterboxHeight);
- final int taskArea = computeArea(taskBounds.width(), taskBounds.height());
+
+ final int letterboxWidth = taskInfo.appCompatTaskInfo.topActivityLetterboxWidth;
+ final int letterboxHeight = taskInfo.appCompatTaskInfo.topActivityLetterboxHeight;
+ final Rect stableBounds = getTaskStableBounds();
+ final int appWidth = stableBounds.width();
+ final int appHeight = stableBounds.height();
+ // App is floating, should always show restart button.
+ if (appWidth > letterboxWidth && appHeight > letterboxHeight) {
+ return true;
+ }
+ // If app fills the width of the display, don't show restart button (for landscape apps)
+ // if device has a custom tolerance value.
+ if (mHideScmTolerance != mCompatUIConfiguration.getDefaultHideRestartButtonTolerance()
+ && appWidth == letterboxWidth) {
+ return false;
+ }
+
+ final int letterboxArea = letterboxWidth * letterboxHeight;
+ final int taskArea = appWidth * appHeight;
if (letterboxArea == 0 || taskArea == 0) {
return false;
}
@@ -234,13 +250,6 @@
return percentageAreaOfLetterboxInTask < mHideScmTolerance;
}
- private int computeArea(int width, int height) {
- if (width == 0 || height == 0) {
- return 0;
- }
- return width * height;
- }
-
private void updateVisibilityOfViews() {
if (mLayout == null) {
return;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
index 17121c8..e729c7d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
@@ -891,13 +891,13 @@
@WMSingleton
@Provides
- static Optional<DesktopTasksController> providesDesktopTasksController(
+ static Optional<DesktopTasksController> providesDesktopTasksController(Context context,
@DynamicOverride Optional<Lazy<DesktopTasksController>> desktopTasksController) {
// Use optional-of-lazy for the dependency that this provider relies on.
// Lazy ensures that this provider will not be the cause the dependency is created
// when it will not be returned due to the condition below.
return desktopTasksController.flatMap((lazy)-> {
- if (DesktopModeStatus.isEnabled()) {
+ if (DesktopModeStatus.canEnterDesktopMode(context)) {
return Optional.of(lazy.get());
}
return Optional.empty();
@@ -910,13 +910,13 @@
@WMSingleton
@Provides
- static Optional<DesktopModeTaskRepository> provideDesktopTaskRepository(
+ static Optional<DesktopModeTaskRepository> provideDesktopTaskRepository(Context context,
@DynamicOverride Optional<Lazy<DesktopModeTaskRepository>> desktopModeTaskRepository) {
// Use optional-of-lazy for the dependency that this provider relies on.
// Lazy ensures that this provider will not be the cause the dependency is created
// when it will not be returned due to the condition below.
return desktopModeTaskRepository.flatMap((lazy)-> {
- if (DesktopModeStatus.isEnabled()) {
+ if (DesktopModeStatus.canEnterDesktopMode(context)) {
return Optional.of(lazy.get());
}
return Optional.empty();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
index b574b81..a1910c5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
@@ -221,7 +221,7 @@
Transitions transitions,
Optional<DesktopTasksController> desktopTasksController,
RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer) {
- if (DesktopModeStatus.isEnabled()) {
+ if (DesktopModeStatus.canEnterDesktopMode(context)) {
return new DesktopModeWindowDecorViewModel(
context,
mainExecutor,
@@ -278,8 +278,8 @@
ShellInit init = FreeformComponents.isFreeformEnabled(context)
? shellInit
: null;
- return new FreeformTaskListener(init, shellTaskOrganizer, desktopModeTaskRepository,
- windowDecorViewModel);
+ return new FreeformTaskListener(context, init, shellTaskOrganizer,
+ desktopModeTaskRepository, windowDecorViewModel);
}
@WMSingleton
@@ -535,10 +535,12 @@
@WMSingleton
@Provides
static Optional<DesktopTasksLimiter> provideDesktopTasksLimiter(
+ Context context,
Transitions transitions,
@DynamicOverride DesktopModeTaskRepository desktopModeTaskRepository,
ShellTaskOrganizer shellTaskOrganizer) {
- if (!DesktopModeStatus.isEnabled() || !Flags.enableDesktopWindowingTaskLimit()) {
+ if (!DesktopModeStatus.canEnterDesktopMode(context)
+ || !Flags.enableDesktopWindowingTaskLimit()) {
return Optional.empty();
}
return Optional.of(
@@ -592,23 +594,26 @@
@WMSingleton
@Provides
static Optional<DesktopTasksTransitionObserver> provideDesktopTasksTransitionObserver(
+ Context context,
Optional<DesktopModeTaskRepository> desktopModeTaskRepository,
Transitions transitions,
ShellInit shellInit
) {
return desktopModeTaskRepository.flatMap(repository ->
- Optional.of(new DesktopTasksTransitionObserver(repository, transitions, shellInit))
+ Optional.of(new DesktopTasksTransitionObserver(
+ context, repository, transitions, shellInit))
);
}
@WMSingleton
@Provides
static DesktopModeLoggerTransitionObserver provideDesktopModeLoggerTransitionObserver(
+ Context context,
ShellInit shellInit,
Transitions transitions,
DesktopModeEventLogger desktopModeEventLogger) {
return new DesktopModeLoggerTransitionObserver(
- shellInit, transitions, desktopModeEventLogger);
+ context, shellInit, transitions, desktopModeEventLogger);
}
@WMSingleton
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeLoggerTransitionObserver.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeLoggerTransitionObserver.kt
index a10c7c0..9038aaa 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeLoggerTransitionObserver.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeLoggerTransitionObserver.kt
@@ -20,6 +20,7 @@
import android.app.ActivityTaskManager.INVALID_TASK_ID
import android.app.TaskInfo
import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM
+import android.content.Context
import android.os.IBinder
import android.util.SparseArray
import android.view.SurfaceControl
@@ -49,6 +50,7 @@
* and other transitions that originate both within and outside shell.
*/
class DesktopModeLoggerTransitionObserver(
+ context: Context,
shellInit: ShellInit,
private val transitions: Transitions,
private val desktopModeEventLogger: DesktopModeEventLogger
@@ -57,7 +59,8 @@
private val idSequence: InstanceIdSequence by lazy { InstanceIdSequence(Int.MAX_VALUE) }
init {
- if (Transitions.ENABLE_SHELL_TRANSITIONS && DesktopModeStatus.isEnabled()) {
+ if (Transitions.ENABLE_SHELL_TRANSITIONS &&
+ DesktopModeStatus.canEnterDesktopMode(context)) {
shellInit.addInitCallback(this::onInit, this)
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java
index fcddcad..9bf9fa7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java
@@ -93,8 +93,10 @@
"persist.wm.debug.desktop_max_task_limit", DEFAULT_MAX_TASK_LIMIT);
/**
- * Return {@code true} if desktop windowing is enabled
+ * Return {@code true} if desktop windowing is enabled. Only to be used for testing. Callers
+ * should use {@link #canEnterDesktopMode(Context)} to query the state of desktop windowing.
*/
+ @VisibleForTesting
public static boolean isEnabled() {
return Flags.enableDesktopWindowingMode();
}
@@ -155,9 +157,9 @@
}
/**
- * Return {@code true} if desktop mode can be entered on the current device.
+ * Return {@code true} if desktop mode is enabled and can be entered on the current device.
*/
public static boolean canEnterDesktopMode(@NonNull Context context) {
- return !enforceDeviceRestrictions() || isDesktopModeSupported(context);
+ return (!enforceDeviceRestrictions() || isDesktopModeSupported(context)) && isEnabled();
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
index 08b7c01..f7bfb86 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
@@ -167,7 +167,7 @@
init {
desktopMode = DesktopModeImpl()
- if (DesktopModeStatus.isEnabled()) {
+ if (DesktopModeStatus.canEnterDesktopMode(context)) {
shellInit.addInitCallback({ onInit() }, this)
}
}
@@ -1515,7 +1515,7 @@
@JvmField
val DESKTOP_MODE_INITIAL_BOUNDS_SCALE = SystemProperties
- .getInt("persist.wm.debug.freeform_initial_bounds_scale", 75) / 100f
+ .getInt("persist.wm.debug.desktop_mode_initial_bounds_scale", 75) / 100f
/**
* Check if desktop density override is enabled
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserver.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserver.kt
index 20df264..451e09c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserver.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserver.kt
@@ -16,6 +16,7 @@
package com.android.wm.shell.desktopmode
+import android.content.Context
import android.os.IBinder
import android.view.SurfaceControl
import android.view.WindowManager
@@ -33,13 +34,15 @@
* and other transitions that originate both within and outside shell.
*/
class DesktopTasksTransitionObserver(
+ context: Context,
private val desktopModeTaskRepository: DesktopModeTaskRepository,
private val transitions: Transitions,
shellInit: ShellInit
) : Transitions.TransitionObserver {
init {
- if (Transitions.ENABLE_SHELL_TRANSITIONS && DesktopModeStatus.isEnabled()) {
+ if (Transitions.ENABLE_SHELL_TRANSITIONS &&
+ DesktopModeStatus.canEnterDesktopMode(context)) {
shellInit.addInitCallback(::onInit, this)
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
index 6fea203..a414a55 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
@@ -21,6 +21,7 @@
import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_FREEFORM;
import android.app.ActivityManager.RunningTaskInfo;
+import android.content.Context;
import android.util.SparseArray;
import android.view.SurfaceControl;
@@ -44,6 +45,7 @@
ShellTaskOrganizer.FocusListener {
private static final String TAG = "FreeformTaskListener";
+ private final Context mContext;
private final ShellTaskOrganizer mShellTaskOrganizer;
private final Optional<DesktopModeTaskRepository> mDesktopModeTaskRepository;
private final WindowDecorViewModel mWindowDecorationViewModel;
@@ -56,10 +58,12 @@
}
public FreeformTaskListener(
+ Context context,
ShellInit shellInit,
ShellTaskOrganizer shellTaskOrganizer,
Optional<DesktopModeTaskRepository> desktopModeTaskRepository,
WindowDecorViewModel windowDecorationViewModel) {
+ mContext = context;
mShellTaskOrganizer = shellTaskOrganizer;
mWindowDecorationViewModel = windowDecorationViewModel;
mDesktopModeTaskRepository = desktopModeTaskRepository;
@@ -70,7 +74,7 @@
private void onInit() {
mShellTaskOrganizer.addListenerForType(this, TASK_LISTENER_TYPE_FREEFORM);
- if (DesktopModeStatus.isEnabled()) {
+ if (DesktopModeStatus.canEnterDesktopMode(mContext)) {
mShellTaskOrganizer.addFocusListener(this);
}
}
@@ -92,7 +96,7 @@
t.apply();
}
- if (DesktopModeStatus.isEnabled()) {
+ if (DesktopModeStatus.canEnterDesktopMode(mContext)) {
mDesktopModeTaskRepository.ifPresent(repository -> {
repository.addOrMoveFreeformTaskToTop(taskInfo.taskId);
repository.unminimizeTask(taskInfo.displayId, taskInfo.taskId);
@@ -114,7 +118,7 @@
taskInfo.taskId);
mTasks.remove(taskInfo.taskId);
- if (DesktopModeStatus.isEnabled()) {
+ if (DesktopModeStatus.canEnterDesktopMode(mContext)) {
mDesktopModeTaskRepository.ifPresent(repository -> {
repository.removeFreeformTask(taskInfo.taskId);
repository.unminimizeTask(taskInfo.displayId, taskInfo.taskId);
@@ -125,7 +129,7 @@
repository.updateVisibleFreeformTasks(taskInfo.displayId, taskInfo.taskId, false);
});
}
-
+ mWindowDecorationViewModel.onTaskVanished(taskInfo);
if (!Transitions.ENABLE_SHELL_TRANSITIONS) {
mWindowDecorationViewModel.destroyWindowDecoration(taskInfo);
}
@@ -139,7 +143,7 @@
taskInfo.taskId);
mWindowDecorationViewModel.onTaskInfoChanged(taskInfo);
state.mTaskInfo = taskInfo;
- if (DesktopModeStatus.isEnabled()) {
+ if (DesktopModeStatus.canEnterDesktopMode(mContext)) {
mDesktopModeTaskRepository.ifPresent(repository -> {
if (taskInfo.isVisible) {
if (repository.addActiveTask(taskInfo.displayId, taskInfo.taskId)) {
@@ -161,7 +165,7 @@
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG,
"Freeform Task Focus Changed: #%d focused=%b",
taskInfo.taskId, taskInfo.isFocused);
- if (DesktopModeStatus.isEnabled() && taskInfo.isFocused) {
+ if (DesktopModeStatus.canEnterDesktopMode(mContext) && taskInfo.isFocused) {
mDesktopModeTaskRepository.ifPresent(repository -> {
repository.addOrMoveFreeformTaskToTop(taskInfo.taskId);
repository.unminimizeTask(taskInfo.displayId, taskInfo.taskId);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenTaskListener.java
index 998728d6..2626e73 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenTaskListener.java
@@ -161,7 +161,7 @@
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Fullscreen Task Vanished: #%d",
taskInfo.taskId);
mTasks.remove(taskInfo.taskId);
-
+ mWindowDecorViewModelOptional.ifPresent(v -> v.onTaskVanished(taskInfo));
if (Transitions.ENABLE_SHELL_TRANSITIONS) return;
if (mWindowDecorViewModelOptional.isPresent()) {
mWindowDecorViewModelOptional.get().destroyWindowDecoration(taskInfo);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java
index 12dce5b..8b2d0dd 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java
@@ -45,7 +45,6 @@
import androidx.annotation.Nullable;
import com.android.internal.util.Preconditions;
-import com.android.wm.shell.R;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.pip.PipBoundsAlgorithm;
import com.android.wm.shell.common.pip.PipBoundsState;
@@ -64,6 +63,9 @@
private static final String TAG = PipTransition.class.getSimpleName();
private static final String PIP_TASK_TOKEN = "pip_task_token";
private static final String PIP_TASK_LEASH = "pip_task_leash";
+ private static final String PIP_START_TX = "pip_start_tx";
+ private static final String PIP_FINISH_TX = "pip_finish_tx";
+ private static final String PIP_DESTINATION_BOUNDS = "pip_dest_bounds";
/**
* The fixed start delay in ms when fading out the content overlay from bounds animation.
@@ -98,6 +100,8 @@
private WindowContainerToken mPipTaskToken;
@Nullable
private SurfaceControl mPipLeash;
+ @Nullable
+ private Transitions.TransitionFinishCallback mFinishCallback;
public PipTransition(
Context context,
@@ -223,7 +227,6 @@
return startExpandAnimation(info, startTransaction, finishTransaction, finishCallback);
} else if (transition == mResizeTransition) {
mResizeTransition = null;
- mPipTransitionState.setState(PipTransitionState.CHANGING_PIP_BOUNDS);
return startResizeAnimation(info, startTransaction, finishTransaction, finishCallback);
}
@@ -246,31 +249,27 @@
return false;
}
SurfaceControl pipLeash = pipChange.getLeash();
- Rect destinationBounds = pipChange.getEndAbsBounds();
// Even though the final bounds and crop are applied with finishTransaction since
// this is a visible change, we still need to handle the app draw coming in. Snapshot
// covering app draw during collection will be removed by startTransaction. So we make
- // the crop equal to the final bounds and then scale the leash back to starting bounds.
+ // the crop equal to the final bounds and then let the current
+ // animator scale the leash back to starting bounds.
+ // Note: animator is responsible for applying the startTx but NOT finishTx.
startTransaction.setWindowCrop(pipLeash, pipChange.getEndAbsBounds().width(),
pipChange.getEndAbsBounds().height());
- startTransaction.setScale(pipLeash,
- (float) mPipBoundsState.getBounds().width() / destinationBounds.width(),
- (float) mPipBoundsState.getBounds().height() / destinationBounds.height());
- startTransaction.apply();
- finishTransaction.setScale(pipLeash,
- (float) mPipBoundsState.getBounds().width() / destinationBounds.width(),
- (float) mPipBoundsState.getBounds().height() / destinationBounds.height());
-
- // We are done with the transition, but will continue animating leash to final bounds.
- finishCallback.onTransitionFinished(null);
-
- // Animate the pip leash with the new buffer
- final int duration = mContext.getResources().getInteger(
- R.integer.config_pipResizeAnimationDuration);
// TODO: b/275910498 Couple this routine with a new implementation of the PiP animator.
- startResizeAnimation(pipLeash, mPipBoundsState.getBounds(), destinationBounds, duration);
+ // Classes interested in continuing the animation would subscribe to this state update
+ // getting info such as endBounds, startTx, and finishTx as an extra Bundle once
+ // animators are in place. Once done state needs to be updated to CHANGED_PIP_BOUNDS.
+ Bundle extra = new Bundle();
+ extra.putParcelable(PIP_START_TX, startTransaction);
+ extra.putParcelable(PIP_FINISH_TX, finishTransaction);
+ extra.putParcelable(PIP_DESTINATION_BOUNDS, pipChange.getEndAbsBounds());
+
+ mFinishCallback = finishCallback;
+ mPipTransitionState.setState(PipTransitionState.CHANGING_PIP_BOUNDS, extra);
return true;
}
@@ -285,12 +284,17 @@
WindowContainerToken pipTaskToken = pipChange.getContainer();
SurfaceControl pipLeash = pipChange.getLeash();
+ if (pipTaskToken == null || pipLeash == null) {
+ return false;
+ }
+
PictureInPictureParams params = pipChange.getTaskInfo().pictureInPictureParams;
Rect srcRectHint = params.getSourceRectHint();
Rect startBounds = pipChange.getStartAbsBounds();
Rect destinationBounds = pipChange.getEndAbsBounds();
WindowContainerTransaction finishWct = new WindowContainerTransaction();
+ SurfaceControl.Transaction tx = new SurfaceControl.Transaction();
if (PipBoundsAlgorithm.isSourceRectHintValidForEnterPip(srcRectHint, destinationBounds)) {
final float scale = (float) destinationBounds.width() / srcRectHint.width();
@@ -316,19 +320,17 @@
.reparent(overlayLeash, pipLeash)
.setLayer(overlayLeash, Integer.MAX_VALUE);
- if (pipTaskToken != null) {
- SurfaceControl.Transaction tx = new SurfaceControl.Transaction();
- tx.addTransactionCommittedListener(mPipScheduler.getMainExecutor(),
- this::onClientDrawAtTransitionEnd)
- .setScale(overlayLeash, 1f, 1f)
- .setPosition(overlayLeash,
- (destinationBounds.width() - overlaySize) / 2f,
- (destinationBounds.height() - overlaySize) / 2f);
- finishWct.setBoundsChangeTransaction(pipTaskToken, tx);
- }
+ // Overlay needs to be adjusted once a new draw comes in resetting surface transform.
+ tx.setScale(overlayLeash, 1f, 1f);
+ tx.setPosition(overlayLeash, (destinationBounds.width() - overlaySize) / 2f,
+ (destinationBounds.height() - overlaySize) / 2f);
}
startTransaction.apply();
+ tx.addTransactionCommittedListener(mPipScheduler.getMainExecutor(),
+ this::onClientDrawAtTransitionEnd);
+ finishWct.setBoundsChangeTransaction(pipTaskToken, tx);
+
// Note that finishWct should be free of any actual WM state changes; we are using
// it for syncing with the client draw after delayed configuration changes are dispatched.
finishCallback.onTransitionFinished(finishWct.isEmpty() ? null : finishWct);
@@ -412,14 +414,6 @@
return true;
}
- /**
- * TODO: b/275910498 Use a new implementation of the PiP animator here.
- */
- private void startResizeAnimation(SurfaceControl leash, Rect startBounds,
- Rect endBounds, int duration) {
- mPipTransitionState.setState(PipTransitionState.CHANGED_PIP_BOUNDS);
- }
-
//
// Various helpers to resolve transition requests and infos
//
@@ -537,6 +531,15 @@
mPipTransitionState.mPipTaskToken = null;
mPipTransitionState.mPinnedTaskLeash = null;
break;
+ case PipTransitionState.CHANGED_PIP_BOUNDS:
+ // Note: this might not be the end of the animation, rather animator just finished
+ // adjusting startTx and finishTx and is ready to finishTransition(). The animator
+ // can still continue playing the leash into the destination bounds after.
+ if (mFinishCallback != null) {
+ mFinishCallback.onTransitionFinished(null);
+ mFinishCallback = null;
+ }
+ break;
}
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransitionState.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransitionState.java
index f7bc622..9a9c59e2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransitionState.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransitionState.java
@@ -257,6 +257,7 @@
private String stateToString() {
switch (mState) {
case UNDEFINED: return "undefined";
+ case SWIPING_TO_PIP: return "swiping_to_pip";
case ENTERING_PIP: return "entering-pip";
case ENTERED_PIP: return "entered-pip";
case CHANGING_PIP_BOUNDS: return "changing-bounds";
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java
index e7d9812..a8611d9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java
@@ -327,7 +327,8 @@
private boolean shouldEnableRunningTasksForDesktopMode() {
return mPcFeatureEnabled
- || (DesktopModeStatus.isEnabled() && enableDesktopWindowingTaskbarRunningApps());
+ || (DesktopModeStatus.canEnterDesktopMode(mContext)
+ && enableDesktopWindowingTaskbarRunningApps());
}
@VisibleForTesting
@@ -371,8 +372,13 @@
continue;
}
- if (DesktopModeStatus.isEnabled() && mDesktopModeTaskRepository.isPresent()
+ if (DesktopModeStatus.canEnterDesktopMode(mContext)
+ && mDesktopModeTaskRepository.isPresent()
&& mDesktopModeTaskRepository.get().isActiveTask(taskInfo.taskId)) {
+ if (mDesktopModeTaskRepository.get().isMinimizedTask(taskInfo.taskId)) {
+ // Minimized freeform tasks should not be shown at all.
+ continue;
+ }
// Freeform tasks will be added as a separate entry
if (mostRecentFreeformTaskIndex == Integer.MAX_VALUE) {
mostRecentFreeformTaskIndex = recentTasks.size();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java
index 6aad4e2..8df287d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java
@@ -69,7 +69,9 @@
default void onSplitVisibilityChanged(boolean visible) {}
}
- /** Callback interface for listening to requests to enter split select */
+ /**
+ * Callback interface for listening to requests to enter split select. Used for desktop -> split
+ */
interface SplitSelectListener {
default boolean onRequestEnterSplitSelect(ActivityManager.RunningTaskInfo taskInfo,
int splitPosition, Rect taskBounds) {
@@ -90,6 +92,24 @@
/** Unregisters listener that gets split screen callback. */
void unregisterSplitScreenListener(@NonNull SplitScreenListener listener);
+ interface SplitInvocationListener {
+ /**
+ * Called whenever shell starts or stops the split screen animation
+ * @param animationRunning if {@code true} the animation has begun, if {@code false} the
+ * animation has finished
+ */
+ default void onSplitAnimationInvoked(boolean animationRunning) { }
+ }
+
+ /**
+ * Registers a {@link SplitInvocationListener} to notify when the animation to enter split
+ * screen has started and stopped
+ *
+ * @param executor callbacks to the listener will be executed on this executor
+ */
+ void registerSplitAnimationListener(@NonNull SplitInvocationListener listener,
+ @NonNull Executor executor);
+
/** Called when device waking up finished. */
void onFinishedWakingUp();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
index 547457b..b9d70e1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
@@ -1166,6 +1166,12 @@
}
@Override
+ public void registerSplitAnimationListener(@NonNull SplitInvocationListener listener,
+ @NonNull Executor executor) {
+ mStageCoordinator.registerSplitAnimationListener(listener, executor);
+ }
+
+ @Override
public void onFinishedWakingUp() {
mMainExecutor.execute(SplitScreenController.this::onFinishedWakingUp);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java
index 1a53a1d..6e5b767 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java
@@ -55,6 +55,7 @@
import com.android.wm.shell.transition.Transitions;
import java.util.ArrayList;
+import java.util.concurrent.Executor;
/** Manages transition animations for split-screen. */
class SplitScreenTransitions {
@@ -79,6 +80,8 @@
private Transitions.TransitionFinishCallback mFinishCallback = null;
private SurfaceControl.Transaction mFinishTransaction;
+ private SplitScreen.SplitInvocationListener mSplitInvocationListener;
+ private Executor mSplitInvocationListenerExecutor;
SplitScreenTransitions(@NonNull TransactionPool pool, @NonNull Transitions transitions,
@NonNull Runnable onFinishCallback, StageCoordinator stageCoordinator) {
@@ -353,6 +356,10 @@
+ " skip to start enter split transition since it already exist. ");
return null;
}
+ if (mSplitInvocationListenerExecutor != null && mSplitInvocationListener != null) {
+ mSplitInvocationListenerExecutor.execute(() -> mSplitInvocationListener
+ .onSplitAnimationInvoked(true /*animationRunning*/));
+ }
final IBinder transition = mTransitions.startTransition(transitType, wct, handler);
setEnterTransition(transition, remoteTransition, extraTransitType, resizeAnim);
return transition;
@@ -457,6 +464,7 @@
mPendingEnter.onConsumed(aborted);
mPendingEnter = null;
+ mStageCoordinator.notifySplitAnimationFinished();
ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "onTransitionConsumed for enter transition");
} else if (isPendingDismiss(transition)) {
mPendingDismiss.onConsumed(aborted);
@@ -529,6 +537,12 @@
mTransitions.getAnimExecutor().execute(va::start);
}
+ public void registerSplitAnimListener(@NonNull SplitScreen.SplitInvocationListener listener,
+ @NonNull Executor executor) {
+ mSplitInvocationListener = listener;
+ mSplitInvocationListenerExecutor = executor;
+ }
+
/** Calls when the transition got consumed. */
interface TransitionConsumedCallback {
void onConsumed(boolean aborted);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index 5e9451a..b10176d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -157,6 +157,7 @@
import java.util.List;
import java.util.Optional;
import java.util.Set;
+import java.util.concurrent.Executor;
/**
* Coordinates the staging (visibility, sizing, ...) of the split-screen {@link MainStage} and
@@ -237,6 +238,9 @@
private DefaultMixedHandler mMixedHandler;
private final Toast mSplitUnsupportedToast;
private SplitRequest mSplitRequest;
+ /** Used to notify others of when shell is animating into split screen */
+ private SplitScreen.SplitInvocationListener mSplitInvocationListener;
+ private Executor mSplitInvocationListenerExecutor;
/**
* Since StageCoordinator only coordinates MainStage and SideStage, it shouldn't support
@@ -247,6 +251,14 @@
return false;
}
+ /** NOTE: Will overwrite any previously set {@link #mSplitInvocationListener} */
+ public void registerSplitAnimationListener(
+ @NonNull SplitScreen.SplitInvocationListener listener, @NonNull Executor executor) {
+ mSplitInvocationListener = listener;
+ mSplitInvocationListenerExecutor = executor;
+ mSplitTransitions.registerSplitAnimListener(listener, executor);
+ }
+
class SplitRequest {
@SplitPosition
int mActivatePosition;
@@ -535,7 +547,7 @@
null /* childrenToTop */, EXIT_REASON_UNKNOWN));
Log.w(TAG, splitFailureMessage("startShortcut",
"side stage was not populated"));
- mSplitUnsupportedToast.show();
+ handleUnsupportedSplitStart();
}
if (finishedCallback != null) {
@@ -666,7 +678,7 @@
null /* childrenToTop */, EXIT_REASON_UNKNOWN));
Log.w(TAG, splitFailureMessage("startIntentLegacy",
"side stage was not populated"));
- mSplitUnsupportedToast.show();
+ handleUnsupportedSplitStart();
}
if (apps != null) {
@@ -1287,7 +1299,7 @@
? mSideStage : mMainStage, EXIT_REASON_UNKNOWN));
Log.w(TAG, splitFailureMessage("onRemoteAnimationFinishedOrCancelled",
"main or side stage was not populated."));
- mSplitUnsupportedToast.show();
+ handleUnsupportedSplitStart();
} else {
mSyncQueue.queue(evictWct);
mSyncQueue.runInSync(t -> {
@@ -1308,7 +1320,7 @@
? mSideStage : mMainStage, EXIT_REASON_UNKNOWN));
Log.w(TAG, splitFailureMessage("onRemoteAnimationFinished",
"main or side stage was not populated"));
- mSplitUnsupportedToast.show();
+ handleUnsupportedSplitStart();
return;
}
@@ -2890,6 +2902,7 @@
if (hasEnteringPip) {
mMixedHandler.animatePendingEnterPipFromSplit(transition, info,
startTransaction, finishTransaction, finishCallback);
+ notifySplitAnimationFinished();
return true;
}
@@ -2924,6 +2937,7 @@
// the transition, or synchronize task-org callbacks.
}
// Use normal animations.
+ notifySplitAnimationFinished();
return false;
} else if (mMixedHandler != null && TransitionUtil.hasDisplayChange(info)) {
// A display-change has been un-expectedly inserted into the transition. Redirect
@@ -2937,6 +2951,7 @@
mSplitLayout.update(startTransaction, true /* resetImePosition */);
startTransaction.apply();
}
+ notifySplitAnimationFinished();
return true;
}
}
@@ -3110,7 +3125,7 @@
pendingEnter.mRemoteHandler.onTransitionConsumed(transition,
false /*aborted*/, finishT);
}
- mSplitUnsupportedToast.show();
+ handleUnsupportedSplitStart();
return true;
}
}
@@ -3139,6 +3154,7 @@
final TransitionInfo.Change finalMainChild = mainChild;
final TransitionInfo.Change finalSideChild = sideChild;
enterTransition.setFinishedCallback((callbackWct, callbackT) -> {
+ notifySplitAnimationFinished();
if (finalMainChild != null) {
if (!mainNotContainOpenTask) {
mMainStage.evictOtherChildren(callbackWct, finalMainChild.getTaskInfo().taskId);
@@ -3560,6 +3576,19 @@
mSplitLayout.isLeftRightSplit());
}
+ private void handleUnsupportedSplitStart() {
+ mSplitUnsupportedToast.show();
+ notifySplitAnimationFinished();
+ }
+
+ void notifySplitAnimationFinished() {
+ if (mSplitInvocationListener == null || mSplitInvocationListenerExecutor == null) {
+ return;
+ }
+ mSplitInvocationListenerExecutor.execute(() ->
+ mSplitInvocationListener.onSplitAnimationInvoked(false /*animationRunning*/));
+ }
+
/**
* Logs the exit of splitscreen to a specific stage. This must be called before the exit is
* executed.
@@ -3622,7 +3651,7 @@
if (!ENABLE_SHELL_TRANSITIONS) {
StageCoordinator.this.exitSplitScreen(isMainStage ? mMainStage : mSideStage,
EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW);
- mSplitUnsupportedToast.show();
+ handleUnsupportedSplitStart();
return;
}
@@ -3642,7 +3671,7 @@
"app package " + taskInfo.baseActivity.getPackageName()
+ " does not support splitscreen, or is a controlled activity type"));
if (splitScreenVisible) {
- mSplitUnsupportedToast.show();
+ handleUnsupportedSplitStart();
}
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
index f41bca3..1e305c5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
@@ -260,6 +260,7 @@
public void onTaskVanished(ActivityManager.RunningTaskInfo taskInfo) {
ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "onTaskVanished: task=%d", taskInfo.taskId);
final int taskId = taskInfo.taskId;
+ mWindowDecorViewModel.ifPresent(vm -> vm.onTaskVanished(taskInfo));
if (mRootTaskInfo.taskId == taskId) {
mCallbacks.onRootTaskVanished();
mRootTaskInfo = null;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
index 9b2922d..4d3c763 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
@@ -61,6 +61,7 @@
import android.view.WindowManager;
import android.window.ITransitionPlayer;
import android.window.RemoteTransition;
+import android.window.TaskFragmentOrganizer;
import android.window.TransitionFilter;
import android.window.TransitionInfo;
import android.window.TransitionMetrics;
@@ -183,6 +184,13 @@
/** Transition to resize PiP task. */
public static final int TRANSIT_RESIZE_PIP = TRANSIT_FIRST_CUSTOM + 16;
+ /**
+ * The task fragment drag resize transition used by activity embedding.
+ */
+ public static final int TRANSIT_TASK_FRAGMENT_DRAG_RESIZE =
+ // TRANSIT_FIRST_CUSTOM + 17
+ TaskFragmentOrganizer.TASK_FRAGMENT_TRANSIT_DRAG_RESIZE;
+
private final ShellTaskOrganizer mOrganizer;
private final Context mContext;
private final ShellExecutor mMainExecutor;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
index 87dc391..e85cb64 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
@@ -119,6 +119,21 @@
}
@Override
+ public void onTaskVanished(RunningTaskInfo taskInfo) {
+ // A task vanishing doesn't necessarily mean the task was closed, it could also mean its
+ // windowing mode changed. We're only interested in closing tasks so checking whether
+ // its info still exists in the task organizer is one way to disambiguate.
+ final boolean closed = mTaskOrganizer.getRunningTaskInfo(taskInfo.taskId) == null;
+ if (closed) {
+ // Destroying the window decoration is usually handled when a TRANSIT_CLOSE transition
+ // changes happen, but there are certain cases in which closing tasks aren't included
+ // in transitions, such as when a non-visible task is closed. See b/296921167.
+ // Destroy the decoration here in case the lack of transition missed it.
+ destroyWindowDecoration(taskInfo);
+ }
+ }
+
+ @Override
public void onTaskChanging(
RunningTaskInfo taskInfo,
SurfaceControl taskSurface,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
index 01175f5..f3ef7c1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
@@ -35,6 +35,7 @@
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
import static com.android.wm.shell.compatui.AppCompatUtils.isSingleTopActivityTranslucent;
import static com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.IndicatorType.TO_FULLSCREEN_INDICATOR;
+import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE;
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_UNDEFINED;
import android.annotation.NonNull;
@@ -72,6 +73,7 @@
import androidx.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.window.flags.Flags;
import com.android.wm.shell.R;
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
@@ -276,7 +278,7 @@
public void onTaskStageChanged(int taskId, @StageType int stage, boolean visible) {
if (visible && stage != STAGE_TYPE_UNDEFINED) {
DesktopModeWindowDecoration decor = mWindowDecorByTaskId.get(taskId);
- if (decor != null && DesktopModeStatus.isEnabled()) {
+ if (decor != null && DesktopModeStatus.canEnterDesktopMode(mContext)) {
mDesktopTasksController.moveToSplit(decor.mTaskInfo);
}
}
@@ -309,6 +311,22 @@
}
@Override
+ public void onTaskVanished(RunningTaskInfo taskInfo) {
+ // A task vanishing doesn't necessarily mean the task was closed, it could also mean its
+ // windowing mode changed. We're only interested in closing tasks so checking whether
+ // its info still exists in the task organizer is one way to disambiguate.
+ final boolean closed = mTaskOrganizer.getRunningTaskInfo(taskInfo.taskId) == null;
+ ProtoLog.v(WM_SHELL_DESKTOP_MODE, "Task Vanished: #%d closed=%b", taskInfo.taskId, closed);
+ if (closed) {
+ // Destroying the window decoration is usually handled when a TRANSIT_CLOSE transition
+ // changes happen, but there are certain cases in which closing tasks aren't included
+ // in transitions, such as when a non-visible task is closed. See b/296921167.
+ // Destroy the decoration here in case the lack of transition missed it.
+ destroyWindowDecoration(taskInfo);
+ }
+ }
+
+ @Override
public void onTaskChanging(
RunningTaskInfo taskInfo,
SurfaceControl taskSurface,
@@ -594,7 +612,7 @@
public boolean handleMotionEvent(@Nullable View v, MotionEvent e) {
final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(mTaskId);
final RunningTaskInfo taskInfo = decoration.mTaskInfo;
- if (DesktopModeStatus.isEnabled()
+ if (DesktopModeStatus.canEnterDesktopMode(mContext)
&& taskInfo.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) {
return false;
}
@@ -771,7 +789,7 @@
*/
private void handleReceivedMotionEvent(MotionEvent ev, InputMonitor inputMonitor) {
final DesktopModeWindowDecoration relevantDecor = getRelevantWindowDecor(ev);
- if (DesktopModeStatus.isEnabled()) {
+ if (DesktopModeStatus.canEnterDesktopMode(mContext)) {
if (!mInImmersiveMode && (relevantDecor == null
|| relevantDecor.mTaskInfo.getWindowingMode() != WINDOWING_MODE_FREEFORM
|| mTransitionDragActive)) {
@@ -780,7 +798,7 @@
}
handleEventOutsideCaption(ev, relevantDecor);
// Prevent status bar from reacting to a caption drag.
- if (DesktopModeStatus.isEnabled()) {
+ if (DesktopModeStatus.canEnterDesktopMode(mContext)) {
if (mTransitionDragActive) {
inputMonitor.pilferPointers();
}
@@ -838,7 +856,7 @@
mDragToDesktopAnimationStartBounds.set(
relevantDecor.mTaskInfo.configuration.windowConfiguration.getBounds());
boolean dragFromStatusBarAllowed = false;
- if (DesktopModeStatus.isEnabled()) {
+ if (DesktopModeStatus.canEnterDesktopMode(mContext)) {
// In proto2 any full screen or multi-window task can be dragged to
// freeform.
final int windowingMode = relevantDecor.mTaskInfo.getWindowingMode();
@@ -1013,12 +1031,11 @@
&& isSingleTopActivityTranslucent(taskInfo)) {
return false;
}
- return DesktopModeStatus.isEnabled()
+ return DesktopModeStatus.canEnterDesktopMode(mContext)
&& !DesktopWallpaperActivity.isWallpaperTask(taskInfo)
&& taskInfo.getWindowingMode() != WINDOWING_MODE_PINNED
&& taskInfo.getActivityType() == ACTIVITY_TYPE_STANDARD
- && !taskInfo.configuration.windowConfiguration.isAlwaysOnTop()
- && DesktopModeStatus.canEnterDesktopMode(mContext);
+ && !taskInfo.configuration.windowConfiguration.isAlwaysOnTop();
}
private void createWindowDecoration(
@@ -1087,7 +1104,8 @@
private void dump(PrintWriter pw, String prefix) {
final String innerPrefix = prefix + " ";
pw.println(prefix + "DesktopModeWindowDecorViewModel");
- pw.println(innerPrefix + "DesktopModeStatus=" + DesktopModeStatus.isEnabled());
+ pw.println(innerPrefix + "DesktopModeStatus="
+ + DesktopModeStatus.canEnterDesktopMode(mContext));
pw.println(innerPrefix + "mTransitionDragActive=" + mTransitionDragActive);
pw.println(innerPrefix + "mEventReceiversByDisplay=" + mEventReceiversByDisplay);
pw.println(innerPrefix + "mWindowDecorByTaskId=" + mWindowDecorByTaskId);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
index 8c6bc73..f7516da 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
@@ -638,7 +638,7 @@
.setOnClickListener(mOnCaptionButtonClickListener)
.setOnTouchListener(mOnCaptionTouchListener)
.setLayoutId(mRelayoutParams.mLayoutResId)
- .setWindowingButtonsVisible(DesktopModeStatus.isEnabled())
+ .setWindowingButtonsVisible(DesktopModeStatus.canEnterDesktopMode(mContext))
.setCaptionHeight(mResult.mCaptionHeight)
.build();
mWindowDecorViewHolder.onHandleMenuOpened();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MaximizeMenu.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MaximizeMenu.kt
index 899b7cc..22f0adc 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MaximizeMenu.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MaximizeMenu.kt
@@ -16,6 +16,9 @@
package com.android.wm.shell.windowdecor
+import android.animation.AnimatorSet
+import android.animation.ObjectAnimator
+import android.animation.ValueAnimator
import android.annotation.IdRes
import android.app.ActivityManager.RunningTaskInfo
import android.content.Context
@@ -30,16 +33,21 @@
import android.view.View.OnClickListener
import android.view.View.OnGenericMotionListener
import android.view.View.OnTouchListener
+import android.view.View.SCALE_Y
+import android.view.View.TRANSLATION_Y
+import android.view.View.TRANSLATION_Z
import android.view.WindowManager
import android.view.WindowlessWindowManager
import android.widget.Button
import android.widget.FrameLayout
import android.widget.LinearLayout
+import android.widget.TextView
import android.window.TaskConstants
import androidx.core.content.withStyledAttributes
import com.android.internal.R.attr.colorAccentPrimary
import com.android.wm.shell.R
import com.android.wm.shell.RootTaskDisplayAreaOrganizer
+import com.android.wm.shell.animation.Interpolators.EMPHASIZED_DECELERATE
import com.android.wm.shell.common.DisplayController
import com.android.wm.shell.common.SyncTransactionQueue
import com.android.wm.shell.windowdecor.WindowDecoration.AdditionalWindow
@@ -65,14 +73,13 @@
private var maximizeMenu: AdditionalWindow? = null
private lateinit var viewHost: SurfaceControlViewHost
private lateinit var leash: SurfaceControl
- private val shadowRadius = loadDimensionPixelSize(
- R.dimen.desktop_mode_maximize_menu_shadow_radius
- ).toFloat()
+ private val openMenuAnimatorSet = AnimatorSet()
private val cornerRadius = loadDimensionPixelSize(
R.dimen.desktop_mode_maximize_menu_corner_radius
).toFloat()
private val menuWidth = loadDimensionPixelSize(R.dimen.desktop_mode_maximize_menu_width)
private val menuHeight = loadDimensionPixelSize(R.dimen.desktop_mode_maximize_menu_height)
+ private val menuPadding = loadDimensionPixelSize(R.dimen.desktop_mode_menu_padding)
private lateinit var snapRightButton: Button
private lateinit var snapLeftButton: Button
@@ -91,10 +98,12 @@
if (maximizeMenu != null) return
createMaximizeMenu()
setupMaximizeMenu()
+ animateOpenMenu()
}
/** Closes the maximize window and releases its view. */
fun close() {
+ openMenuAnimatorSet.cancel()
maximizeMenu?.releaseView()
maximizeMenu = null
}
@@ -134,8 +143,6 @@
// Bring menu to front when open
t.setLayer(leash, TaskConstants.TASK_CHILD_LAYER_FLOATING_MENU)
.setPosition(leash, menuPosition.x, menuPosition.y)
- .setWindowCrop(leash, menuWidth, menuHeight)
- .setShadowRadius(leash, shadowRadius)
.setCornerRadius(leash, cornerRadius)
.show(leash)
maximizeMenu = AdditionalWindow(leash, viewHost, transactionSupplier)
@@ -146,6 +153,77 @@
}
}
+ private fun animateOpenMenu() {
+ val viewHost = maximizeMenu?.mWindowViewHost
+ val maximizeMenuView = viewHost?.view ?: return
+ val maximizeWindowText = maximizeMenuView.requireViewById<TextView>(
+ R.id.maximize_menu_maximize_window_text)
+ val snapWindowText = maximizeMenuView.requireViewById<TextView>(
+ R.id.maximize_menu_snap_window_text)
+
+ openMenuAnimatorSet.playTogether(
+ ObjectAnimator.ofFloat(maximizeMenuView, SCALE_Y, STARTING_MENU_HEIGHT_SCALE, 1f)
+ .apply {
+ duration = MENU_HEIGHT_ANIMATION_DURATION_MS
+ interpolator = EMPHASIZED_DECELERATE
+ },
+ ValueAnimator.ofFloat(STARTING_MENU_HEIGHT_SCALE, 1f)
+ .apply {
+ duration = MENU_HEIGHT_ANIMATION_DURATION_MS
+ interpolator = EMPHASIZED_DECELERATE
+ addUpdateListener {
+ // Animate padding so that controls stay pinned to the bottom of
+ // the menu.
+ val value = animatedValue as Float
+ val topPadding = menuPadding -
+ ((1 - value) * menuHeight).toInt()
+ maximizeMenuView.setPadding(menuPadding, topPadding,
+ menuPadding, menuPadding)
+ }
+ },
+ ValueAnimator.ofFloat(1 / STARTING_MENU_HEIGHT_SCALE, 1f).apply {
+ duration = MENU_HEIGHT_ANIMATION_DURATION_MS
+ interpolator = EMPHASIZED_DECELERATE
+ addUpdateListener {
+ // Scale up the children of the maximize menu so that the menu
+ // scale is cancelled out and only the background is scaled.
+ val value = animatedValue as Float
+ maximizeButtonLayout.scaleY = value
+ snapButtonsLayout.scaleY = value
+ maximizeWindowText.scaleY = value
+ snapWindowText.scaleY = value
+ }
+ },
+ ObjectAnimator.ofFloat(maximizeMenuView, TRANSLATION_Y,
+ (STARTING_MENU_HEIGHT_SCALE - 1) * menuHeight, 0f).apply {
+ duration = MENU_HEIGHT_ANIMATION_DURATION_MS
+ interpolator = EMPHASIZED_DECELERATE
+ },
+ ObjectAnimator.ofInt(maximizeMenuView.background, "alpha",
+ MAX_DRAWABLE_ALPHA_VALUE).apply {
+ duration = ALPHA_ANIMATION_DURATION_MS
+ },
+ ValueAnimator.ofFloat(0f, 1f)
+ .apply {
+ duration = ALPHA_ANIMATION_DURATION_MS
+ startDelay = CONTROLS_ALPHA_ANIMATION_DELAY_MS
+ addUpdateListener {
+ val value = animatedValue as Float
+ maximizeButtonLayout.alpha = value
+ snapButtonsLayout.alpha = value
+ maximizeWindowText.alpha = value
+ snapWindowText.alpha = value
+ }
+ },
+ ObjectAnimator.ofFloat(maximizeMenuView, TRANSLATION_Z, MENU_Z_TRANSLATION)
+ .apply {
+ duration = ELEVATION_ANIMATION_DURATION_MS
+ startDelay = CONTROLS_ALPHA_ANIMATION_DELAY_MS
+ }
+ )
+ openMenuAnimatorSet.start()
+ }
+
private fun loadDimensionPixelSize(resourceId: Int): Int {
return if (resourceId == Resources.ID_NULL) {
0
@@ -263,6 +341,14 @@
}
companion object {
+ // Open menu animation constants
+ private const val ALPHA_ANIMATION_DURATION_MS = 50L
+ private const val MAX_DRAWABLE_ALPHA_VALUE = 255
+ private const val STARTING_MENU_HEIGHT_SCALE = 0.8f
+ private const val MENU_HEIGHT_ANIMATION_DURATION_MS = 300L
+ private const val ELEVATION_ANIMATION_DURATION_MS = 50L
+ private const val CONTROLS_ALPHA_ANIMATION_DELAY_MS = 33L
+ private const val MENU_Z_TRANSLATION = 1f
fun isMaximizeMenuView(@IdRes viewId: Int): Boolean {
return viewId == R.id.maximize_menu ||
viewId == R.id.maximize_menu_maximize_button ||
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecorViewModel.java
index 01a6012..1563259 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecorViewModel.java
@@ -67,6 +67,14 @@
void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo);
/**
+ * Notifies a task has vanished, which can mean that the task changed windowing mode or was
+ * removed.
+ *
+ * @param taskInfo the task info of the task
+ */
+ void onTaskVanished(ActivityManager.RunningTaskInfo taskInfo);
+
+ /**
* Notifies a transition is about to start about the given task to give the window decoration a
* chance to prepare for this transition. Unlike {@link #onTaskInfoChanged}, this method creates
* a window decoration if one does not exist but is required.
diff --git a/libs/WindowManager/Shell/tests/OWNERS b/libs/WindowManager/Shell/tests/OWNERS
index 0f24bb5..b8a19ad 100644
--- a/libs/WindowManager/Shell/tests/OWNERS
+++ b/libs/WindowManager/Shell/tests/OWNERS
@@ -13,3 +13,5 @@
pbdr@google.com
tkachenkoi@google.com
mpodolian@google.com
+jeremysim@google.com
+peanutbutter@google.com
diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/scenarios/CloseAllAppsWithAppHeaderExit.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/scenarios/CloseAllAppsWithAppHeaderExit.kt
index 0c2b501..e77a457 100644
--- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/scenarios/CloseAllAppsWithAppHeaderExit.kt
+++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/scenarios/CloseAllAppsWithAppHeaderExit.kt
@@ -55,7 +55,7 @@
@Before
fun setup() {
- Assume.assumeTrue(Flags.enableDesktopWindowingMode())
+ Assume.assumeTrue(Flags.enableDesktopWindowingMode() && tapl.isTablet)
tapl.setEnableRotation(true)
tapl.setExpectedRotation(rotation.value)
testApp.enterDesktopWithDrag(wmHelper, device)
diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/scenarios/EnterDesktopWithDrag.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/scenarios/EnterDesktopWithDrag.kt
index 9e9998e..fe139d2 100644
--- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/scenarios/EnterDesktopWithDrag.kt
+++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/scenarios/EnterDesktopWithDrag.kt
@@ -50,7 +50,7 @@
@Before
fun setup() {
- Assume.assumeTrue(Flags.enableDesktopWindowingMode())
+ Assume.assumeTrue(Flags.enableDesktopWindowingMode() && tapl.isTablet)
tapl.setEnableRotation(true)
tapl.setExpectedRotation(rotation.value)
}
diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/scenarios/ResizeAppWithCornerResize.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/scenarios/ResizeAppWithCornerResize.kt
index 289ca9f..ac9089a 100644
--- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/scenarios/ResizeAppWithCornerResize.kt
+++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/scenarios/ResizeAppWithCornerResize.kt
@@ -50,7 +50,7 @@
@Before
fun setup() {
- Assume.assumeTrue(Flags.enableDesktopWindowingMode())
+ Assume.assumeTrue(Flags.enableDesktopWindowingMode() && tapl.isTablet)
tapl.setEnableRotation(true)
tapl.setExpectedRotation(rotation.value)
testApp.enterDesktopWithDrag(wmHelper, device)
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunnerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunnerTests.java
index 2ac72af..ea522cd 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunnerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunnerTests.java
@@ -20,6 +20,8 @@
import static android.window.TransitionInfo.FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY;
import static android.window.TransitionInfo.FLAG_IS_BEHIND_STARTING_WINDOW;
+import static com.android.wm.shell.transition.Transitions.TRANSIT_TASK_FRAGMENT_DRAG_RESIZE;
+
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
@@ -100,6 +102,20 @@
}
@Test
+ public void testTransitionTypeDragResize() {
+ final TransitionInfo info = new TransitionInfoBuilder(TRANSIT_TASK_FRAGMENT_DRAG_RESIZE, 0)
+ .addChange(createChange(FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY))
+ .build();
+ final Animator animator = mAnimRunner.createAnimator(
+ info, mStartTransaction, mFinishTransaction,
+ () -> mFinishCallback.onTransitionFinished(null /* wct */),
+ new ArrayList());
+
+ // The animation should be empty when it is a jump cut for drag resize.
+ assertEquals(0, animator.getDuration());
+ }
+
+ @Test
public void testInvalidCustomAnimation() {
final TransitionInfo info = new TransitionInfoBuilder(TRANSIT_OPEN, 0)
.addChange(createChange(FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY))
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java
index 56d0f8e1..8de60b7 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java
@@ -115,27 +115,27 @@
@Test
public void testUpdateDivideBounds() {
- mSplitLayout.updateDivideBounds(anyInt());
+ mSplitLayout.updateDividerBounds(anyInt());
verify(mSplitLayoutHandler).onLayoutSizeChanging(any(SplitLayout.class), anyInt(),
anyInt());
}
@Test
public void testSetDividePosition() {
- mSplitLayout.setDividePosition(100, false /* applyLayoutChange */);
- assertThat(mSplitLayout.getDividePosition()).isEqualTo(100);
+ mSplitLayout.setDividerPosition(100, false /* applyLayoutChange */);
+ assertThat(mSplitLayout.getDividerPosition()).isEqualTo(100);
verify(mSplitLayoutHandler, never()).onLayoutSizeChanged(any(SplitLayout.class));
- mSplitLayout.setDividePosition(200, true /* applyLayoutChange */);
- assertThat(mSplitLayout.getDividePosition()).isEqualTo(200);
+ mSplitLayout.setDividerPosition(200, true /* applyLayoutChange */);
+ assertThat(mSplitLayout.getDividerPosition()).isEqualTo(200);
verify(mSplitLayoutHandler).onLayoutSizeChanged(any(SplitLayout.class));
}
@Test
public void testSetDivideRatio() {
- mSplitLayout.setDividePosition(200, false /* applyLayoutChange */);
+ mSplitLayout.setDividerPosition(200, false /* applyLayoutChange */);
mSplitLayout.setDivideRatio(SNAP_TO_50_50);
- assertThat(mSplitLayout.getDividePosition()).isEqualTo(
+ assertThat(mSplitLayout.getDividerPosition()).isEqualTo(
mSplitLayout.mDividerSnapAlgorithm.getMiddleTarget().position);
}
@@ -152,7 +152,7 @@
DividerSnapAlgorithm.SnapTarget snapTarget = getSnapTarget(0 /* position */,
SNAP_TO_START_AND_DISMISS);
- mSplitLayout.snapToTarget(mSplitLayout.getDividePosition(), snapTarget);
+ mSplitLayout.snapToTarget(mSplitLayout.getDividerPosition(), snapTarget);
waitDividerFlingFinished();
verify(mSplitLayoutHandler).onSnappedToDismiss(eq(false), anyInt());
}
@@ -164,7 +164,7 @@
DividerSnapAlgorithm.SnapTarget snapTarget = getSnapTarget(0 /* position */,
SNAP_TO_END_AND_DISMISS);
- mSplitLayout.snapToTarget(mSplitLayout.getDividePosition(), snapTarget);
+ mSplitLayout.snapToTarget(mSplitLayout.getDividerPosition(), snapTarget);
waitDividerFlingFinished();
verify(mSplitLayoutHandler).onSnappedToDismiss(eq(true), anyInt());
}
@@ -188,7 +188,7 @@
}
private void waitDividerFlingFinished() {
- verify(mSplitLayout).flingDividePosition(anyInt(), anyInt(), anyInt(),
+ verify(mSplitLayout).flingDividerPosition(anyInt(), anyInt(), anyInt(),
mRunnableCaptor.capture());
mRunnableCaptor.getValue().run();
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIWindowManagerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIWindowManagerTest.java
index 5209d0e..41a81c1 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIWindowManagerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIWindowManagerTest.java
@@ -22,6 +22,7 @@
import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED;
import static android.platform.test.flag.junit.SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT;
import static android.view.WindowInsets.Type.navigationBars;
+import static android.view.WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
@@ -98,14 +99,28 @@
private CompatUIWindowManager mWindowManager;
private TaskInfo mTaskInfo;
+ private DisplayLayout mDisplayLayout;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
doReturn(100).when(mCompatUIConfiguration).getHideSizeCompatRestartButtonTolerance();
mTaskInfo = createTaskInfo(/* hasSizeCompat= */ false, CAMERA_COMPAT_CONTROL_HIDDEN);
+
+ final DisplayInfo displayInfo = new DisplayInfo();
+ displayInfo.logicalWidth = TASK_WIDTH;
+ displayInfo.logicalHeight = TASK_HEIGHT;
+ mDisplayLayout = new DisplayLayout(displayInfo,
+ mContext.getResources(), /* hasNavigationBar= */ true, /* hasStatusBar= */ false);
+ final InsetsState insetsState = new InsetsState();
+ insetsState.setDisplayFrame(new Rect(0, 0, TASK_WIDTH, TASK_HEIGHT));
+ final InsetsSource insetsSource = new InsetsSource(
+ InsetsSource.createId(null, 0, navigationBars()), navigationBars());
+ insetsSource.setFrame(0, TASK_HEIGHT - 200, TASK_WIDTH, TASK_HEIGHT);
+ insetsState.addSource(insetsSource);
+ mDisplayLayout.setInsets(mContext.getResources(), insetsState);
mWindowManager = new CompatUIWindowManager(mContext, mTaskInfo, mSyncTransactionQueue,
- mCallback, mTaskListener, new DisplayLayout(), new CompatUIHintsState(),
+ mCallback, mTaskListener, mDisplayLayout, new CompatUIHintsState(),
mCompatUIConfiguration, mOnRestartButtonClicked);
spyOn(mWindowManager);
@@ -363,9 +378,9 @@
// Update if the insets change on the existing display layout
clearInvocations(mWindowManager);
- InsetsState insetsState = new InsetsState();
+ final InsetsState insetsState = new InsetsState();
insetsState.setDisplayFrame(new Rect(0, 0, 1000, 2000));
- InsetsSource insetsSource = new InsetsSource(
+ final InsetsSource insetsSource = new InsetsSource(
InsetsSource.createId(null, 0, navigationBars()), navigationBars());
insetsSource.setFrame(0, 1800, 1000, 2000);
insetsState.addSource(insetsSource);
@@ -493,16 +508,14 @@
@Test
public void testShouldShowSizeCompatRestartButton() {
mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_HIDE_SCM_BUTTON);
-
- doReturn(86).when(mCompatUIConfiguration).getHideSizeCompatRestartButtonTolerance();
+ doReturn(85).when(mCompatUIConfiguration).getHideSizeCompatRestartButtonTolerance();
mWindowManager = new CompatUIWindowManager(mContext, mTaskInfo, mSyncTransactionQueue,
- mCallback, mTaskListener, new DisplayLayout(), new CompatUIHintsState(),
+ mCallback, mTaskListener, mDisplayLayout, new CompatUIHintsState(),
mCompatUIConfiguration, mOnRestartButtonClicked);
// Simulate rotation of activity in square display
TaskInfo taskInfo = createTaskInfo(true, CAMERA_COMPAT_CONTROL_HIDDEN);
- taskInfo.configuration.windowConfiguration.setBounds(new Rect(0, 0, 2000, 2000));
- taskInfo.appCompatTaskInfo.topActivityLetterboxHeight = 2000;
+ taskInfo.appCompatTaskInfo.topActivityLetterboxHeight = TASK_HEIGHT;
taskInfo.appCompatTaskInfo.topActivityLetterboxWidth = 1850;
assertFalse(mWindowManager.shouldShowSizeCompatRestartButton(taskInfo));
@@ -512,11 +525,21 @@
assertTrue(mWindowManager.shouldShowSizeCompatRestartButton(taskInfo));
// Simulate folding
- taskInfo.configuration.windowConfiguration.setBounds(new Rect(0, 0, 1000, 2000));
- assertFalse(mWindowManager.shouldShowSizeCompatRestartButton(taskInfo));
+ final InsetsState insetsState = new InsetsState();
+ insetsState.setDisplayFrame(new Rect(0, 0, 1000, TASK_HEIGHT));
+ final InsetsSource insetsSource = new InsetsSource(
+ InsetsSource.createId(null, 0, navigationBars()), navigationBars());
+ insetsSource.setFrame(0, TASK_HEIGHT - 200, 1000, TASK_HEIGHT);
+ insetsState.addSource(insetsSource);
+ mDisplayLayout.setInsets(mContext.getResources(), insetsState);
+ mWindowManager.updateDisplayLayout(mDisplayLayout);
+ taskInfo.configuration.smallestScreenWidthDp = LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP - 100;
+ assertTrue(mWindowManager.shouldShowSizeCompatRestartButton(taskInfo));
- taskInfo.appCompatTaskInfo.topActivityLetterboxWidth = 1000;
- taskInfo.appCompatTaskInfo.topActivityLetterboxHeight = 500;
+ // Simulate floating app with 90& area, more than tolerance
+ taskInfo.configuration.smallestScreenWidthDp = LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP;
+ taskInfo.appCompatTaskInfo.topActivityLetterboxWidth = 950;
+ taskInfo.appCompatTaskInfo.topActivityLetterboxHeight = 1900;
assertTrue(mWindowManager.shouldShowSizeCompatRestartButton(taskInfo));
}
@@ -529,10 +552,10 @@
cameraCompatControlState;
taskInfo.configuration.uiMode &= ~Configuration.UI_MODE_TYPE_DESK;
// Letterboxed activity that takes half the screen should show size compat restart button
- taskInfo.configuration.windowConfiguration.setBounds(
- new Rect(0, 0, TASK_WIDTH, TASK_HEIGHT));
taskInfo.appCompatTaskInfo.topActivityLetterboxHeight = 1000;
taskInfo.appCompatTaskInfo.topActivityLetterboxWidth = 1000;
+ // Screen width dp larger than a normal phone.
+ taskInfo.configuration.smallestScreenWidthDp = LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP;
return taskInfo;
}
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeLoggerTransitionObserverTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeLoggerTransitionObserverTest.kt
index 65117f7..60a7dcd 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeLoggerTransitionObserverTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeLoggerTransitionObserverTest.kt
@@ -18,6 +18,7 @@
import android.app.ActivityManager
import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM
import android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN
+import android.content.Context
import android.os.IBinder
import android.testing.AndroidTestingRunner
import android.view.SurfaceControl
@@ -35,6 +36,7 @@
import android.window.TransitionInfo.Change
import android.window.WindowContainerToken
import androidx.test.filters.SmallTest
+import com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn
import com.android.modules.utils.testing.ExtendedMockitoRule
import com.android.wm.shell.common.ShellExecutor
import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.EnterReason
@@ -58,6 +60,11 @@
import org.mockito.kotlin.same
import org.mockito.kotlin.times
+/**
+ * Test class for {@link DesktopModeLoggerTransitionObserver}
+ *
+ * Usage: atest WMShellUnitTests:DesktopModeLoggerTransitionObserverTest
+ */
@SmallTest
@RunWith(AndroidTestingRunner::class)
class DesktopModeLoggerTransitionObserverTest {
@@ -74,6 +81,8 @@
private lateinit var mockShellInit: ShellInit
@Mock
private lateinit var transitions: Transitions
+ @Mock
+ private lateinit var context: Context
private lateinit var transitionObserver: DesktopModeLoggerTransitionObserver
private lateinit var shellInit: ShellInit
@@ -81,12 +90,12 @@
@Before
fun setup() {
- Mockito.`when`(DesktopModeStatus.isEnabled()).thenReturn(true)
+ doReturn(true).`when`{ DesktopModeStatus.canEnterDesktopMode(any()) }
shellInit = Mockito.spy(ShellInit(testExecutor))
desktopModeEventLogger = mock(DesktopModeEventLogger::class.java)
transitionObserver = DesktopModeLoggerTransitionObserver(
- mockShellInit, transitions, desktopModeEventLogger)
+ context, mockShellInit, transitions, desktopModeEventLogger)
if (Transitions.ENABLE_SHELL_TRANSITIONS) {
val initRunnableCaptor = ArgumentCaptor.forClass(
Runnable::class.java)
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
index ad4b720..df8a222 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
@@ -159,6 +159,7 @@
mockitoSession = mockitoSession().strictness(Strictness.LENIENT)
.spyStatic(DesktopModeStatus::class.java).startMocking()
whenever(DesktopModeStatus.isEnabled()).thenReturn(true)
+ doReturn(true).`when` { DesktopModeStatus.isDesktopModeSupported(any()) }
shellInit = Mockito.spy(ShellInit(testExecutor))
desktopModeTaskRepository = DesktopModeTaskRepository()
@@ -1347,7 +1348,6 @@
private fun setUpFullscreenTask(displayId: Int = DEFAULT_DISPLAY): RunningTaskInfo {
val task = createFullscreenTask(displayId)
- doReturn(true).`when` { DesktopModeStatus.isDesktopModeSupported(any()) }
whenever(DesktopModeStatus.enforceDeviceRestrictions()).thenReturn(true)
whenever(shellTaskOrganizer.getRunningTaskInfo(task.taskId)).thenReturn(task)
runningTasks.add(task)
@@ -1356,7 +1356,6 @@
private fun setUpSplitScreenTask(displayId: Int = DEFAULT_DISPLAY): RunningTaskInfo {
val task = createSplitScreenTask(displayId)
- doReturn(true).`when` { DesktopModeStatus.isDesktopModeSupported(any()) }
whenever(DesktopModeStatus.enforceDeviceRestrictions()).thenReturn(true)
whenever(splitScreenController.isTaskInSplitScreen(task.taskId)).thenReturn(true)
whenever(shellTaskOrganizer.getRunningTaskInfo(task.taskId)).thenReturn(task)
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksLimiterTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksLimiterTest.kt
index 38ea034..539d5b8 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksLimiterTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksLimiterTest.kt
@@ -27,6 +27,7 @@
import android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REORDER
import androidx.test.filters.SmallTest
import com.android.dx.mockito.inline.extended.ExtendedMockito
+import com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn
import com.android.dx.mockito.inline.extended.StaticMockitoSession
import com.android.wm.shell.ShellTaskOrganizer
import com.android.wm.shell.ShellTestCase
@@ -41,6 +42,7 @@
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
+import org.mockito.Mockito.any
import org.mockito.Mockito.`when`
import org.mockito.quality.Strictness
@@ -69,7 +71,7 @@
fun setUp() {
mockitoSession = ExtendedMockito.mockitoSession().strictness(Strictness.LENIENT)
.spyStatic(DesktopModeStatus::class.java).startMocking()
- `when`(DesktopModeStatus.isEnabled()).thenReturn(true)
+ doReturn(true).`when`{ DesktopModeStatus.canEnterDesktopMode(any()) }
desktopTaskRepo = DesktopModeTaskRepository()
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/freeform/FreeformTaskListenerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/freeform/FreeformTaskListenerTests.java
index 71eea4b..665077b 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/freeform/FreeformTaskListenerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/freeform/FreeformTaskListenerTests.java
@@ -19,11 +19,12 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
import android.app.ActivityManager;
@@ -72,8 +73,10 @@
public void setup() {
mMockitoSession = mockitoSession().initMocks(this)
.strictness(Strictness.LENIENT).mockStatic(DesktopModeStatus.class).startMocking();
- when(DesktopModeStatus.isEnabled()).thenReturn(true);
+ doReturn(true).when(() -> DesktopModeStatus.canEnterDesktopMode(any()));
+
mFreeformTaskListener = new FreeformTaskListener(
+ mContext,
mShellInit,
mTaskOrganizer,
Optional.of(mDesktopModeTaskRepository),
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java
index 40b59c1..240324b 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java
@@ -59,6 +59,7 @@
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.dx.mockito.inline.extended.ExtendedMockito;
import com.android.dx.mockito.inline.extended.StaticMockitoSession;
import com.android.window.flags.Flags;
import com.android.wm.shell.ShellTaskOrganizer;
@@ -75,11 +76,13 @@
import com.android.wm.shell.util.GroupedRecentTaskInfo;
import com.android.wm.shell.util.SplitBounds;
+import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
+import org.mockito.quality.Strictness;
import java.util.ArrayList;
import java.util.Arrays;
@@ -88,7 +91,9 @@
import java.util.function.Consumer;
/**
- * Tests for {@link RecentTasksController}.
+ * Tests for {@link RecentTasksController}
+ *
+ * Usage: atest WMShellUnitTests:RecentTasksControllerTest
*/
@RunWith(AndroidJUnit4.class)
@SmallTest
@@ -118,9 +123,15 @@
private ShellInit mShellInit;
private ShellController mShellController;
private TestShellExecutor mMainExecutor;
+ private static StaticMockitoSession sMockitoSession;
@Before
public void setUp() {
+ sMockitoSession = mockitoSession().initMocks(this).strictness(Strictness.LENIENT)
+ .mockStatic(DesktopModeStatus.class).startMocking();
+ ExtendedMockito.doReturn(true)
+ .when(() -> DesktopModeStatus.canEnterDesktopMode(any()));
+
mMainExecutor = new TestShellExecutor();
when(mContext.getPackageManager()).thenReturn(mock(PackageManager.class));
mShellInit = spy(new ShellInit(mMainExecutor));
@@ -136,6 +147,11 @@
mShellInit.init();
}
+ @After
+ public void tearDown() {
+ sMockitoSession.finishMocking();
+ }
+
@Test
public void instantiateController_addInitCallback() {
verify(mShellInit, times(1)).addInitCallback(any(), isA(RecentTasksController.class));
@@ -275,10 +291,6 @@
@Test
public void testGetRecentTasks_hasActiveDesktopTasks_proto2Enabled_groupFreeformTasks() {
- StaticMockitoSession mockitoSession = mockitoSession().mockStatic(
- DesktopModeStatus.class).startMocking();
- when(DesktopModeStatus.isEnabled()).thenReturn(true);
-
ActivityManager.RecentTaskInfo t1 = makeTaskInfo(1);
ActivityManager.RecentTaskInfo t2 = makeTaskInfo(2);
ActivityManager.RecentTaskInfo t3 = makeTaskInfo(3);
@@ -309,16 +321,10 @@
// Check single entries
assertEquals(t2, singleGroup1.getTaskInfo1());
assertEquals(t4, singleGroup2.getTaskInfo1());
-
- mockitoSession.finishMocking();
}
@Test
public void testGetRecentTasks_hasActiveDesktopTasks_proto2Enabled_freeformTaskOrder() {
- StaticMockitoSession mockitoSession = mockitoSession().mockStatic(
- DesktopModeStatus.class).startMocking();
- when(DesktopModeStatus.isEnabled()).thenReturn(true);
-
ActivityManager.RecentTaskInfo t1 = makeTaskInfo(1);
ActivityManager.RecentTaskInfo t2 = makeTaskInfo(2);
ActivityManager.RecentTaskInfo t3 = makeTaskInfo(3);
@@ -357,15 +363,12 @@
// Check single entry
assertEquals(t4, singleGroup.getTaskInfo1());
-
- mockitoSession.finishMocking();
}
@Test
public void testGetRecentTasks_hasActiveDesktopTasks_proto2Disabled_doNotGroupFreeformTasks() {
- StaticMockitoSession mockitoSession = mockitoSession().mockStatic(
- DesktopModeStatus.class).startMocking();
- when(DesktopModeStatus.isEnabled()).thenReturn(false);
+ ExtendedMockito.doReturn(false)
+ .when(() -> DesktopModeStatus.canEnterDesktopMode(any()));
ActivityManager.RecentTaskInfo t1 = makeTaskInfo(1);
ActivityManager.RecentTaskInfo t2 = makeTaskInfo(2);
@@ -390,8 +393,45 @@
assertEquals(t2, recentTasks.get(1).getTaskInfo1());
assertEquals(t3, recentTasks.get(2).getTaskInfo1());
assertEquals(t4, recentTasks.get(3).getTaskInfo1());
+ }
- mockitoSession.finishMocking();
+ @Test
+ public void testGetRecentTasks_proto2Enabled_ignoresMinimizedFreeformTasks() {
+ ActivityManager.RecentTaskInfo t1 = makeTaskInfo(1);
+ ActivityManager.RecentTaskInfo t2 = makeTaskInfo(2);
+ ActivityManager.RecentTaskInfo t3 = makeTaskInfo(3);
+ ActivityManager.RecentTaskInfo t4 = makeTaskInfo(4);
+ ActivityManager.RecentTaskInfo t5 = makeTaskInfo(5);
+ setRawList(t1, t2, t3, t4, t5);
+
+ when(mDesktopModeTaskRepository.isActiveTask(1)).thenReturn(true);
+ when(mDesktopModeTaskRepository.isActiveTask(3)).thenReturn(true);
+ when(mDesktopModeTaskRepository.isActiveTask(5)).thenReturn(true);
+ when(mDesktopModeTaskRepository.isMinimizedTask(3)).thenReturn(true);
+
+ ArrayList<GroupedRecentTaskInfo> recentTasks = mRecentTasksController.getRecentTasks(
+ MAX_VALUE, RECENT_IGNORE_UNAVAILABLE, 0);
+
+ // 2 freeform tasks should be grouped into one, 1 task should be skipped, 3 total recents
+ // entries
+ assertEquals(3, recentTasks.size());
+ GroupedRecentTaskInfo freeformGroup = recentTasks.get(0);
+ GroupedRecentTaskInfo singleGroup1 = recentTasks.get(1);
+ GroupedRecentTaskInfo singleGroup2 = recentTasks.get(2);
+
+ // Check that groups have expected types
+ assertEquals(GroupedRecentTaskInfo.TYPE_FREEFORM, freeformGroup.getType());
+ assertEquals(GroupedRecentTaskInfo.TYPE_SINGLE, singleGroup1.getType());
+ assertEquals(GroupedRecentTaskInfo.TYPE_SINGLE, singleGroup2.getType());
+
+ // Check freeform group entries
+ assertEquals(2, freeformGroup.getTaskInfoList().size());
+ assertEquals(t1, freeformGroup.getTaskInfoList().get(0));
+ assertEquals(t5, freeformGroup.getTaskInfoList().get(1));
+
+ // Check single entries
+ assertEquals(t2, singleGroup1.getTaskInfo1());
+ assertEquals(t4, singleGroup2.getTaskInfo1());
}
@Test
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
index befc702..34b2eeb 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
@@ -39,10 +39,13 @@
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
import android.annotation.NonNull;
import android.app.ActivityManager;
@@ -63,6 +66,7 @@
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.ShellTestCase;
import com.android.wm.shell.TestRunningTaskInfoBuilder;
+import com.android.wm.shell.TestShellExecutor;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.common.DisplayInsetsController;
@@ -105,6 +109,8 @@
@Mock private ShellExecutor mMainExecutor;
@Mock private LaunchAdjacentController mLaunchAdjacentController;
@Mock private DefaultMixedHandler mMixedHandler;
+ @Mock private SplitScreen.SplitInvocationListener mInvocationListener;
+ private final TestShellExecutor mTestShellExecutor = new TestShellExecutor();
private SplitLayout mSplitLayout;
private MainStage mMainStage;
private SideStage mSideStage;
@@ -147,6 +153,7 @@
.setParentTaskId(mSideStage.mRootTaskInfo.taskId).build();
doReturn(mock(SplitDecorManager.class)).when(mMainStage).getSplitDecorManager();
doReturn(mock(SplitDecorManager.class)).when(mSideStage).getSplitDecorManager();
+ mStageCoordinator.registerSplitAnimationListener(mInvocationListener, mTestShellExecutor);
}
@Test
@@ -452,6 +459,15 @@
mMainStage.activate(new WindowContainerTransaction(), true /* includingTopTask */);
}
+ @Test
+ @UiThreadTest
+ public void testSplitInvocationCallback() {
+ enterSplit();
+ mTestShellExecutor.flushAll();
+ verify(mInvocationListener, times(1))
+ .onSplitAnimationInvoked(eq(true));
+ }
+
private boolean containsSplitEnter(@NonNull WindowContainerTransaction wct) {
for (int i = 0; i < wct.getHierarchyOps().size(); ++i) {
WindowContainerTransaction.HierarchyOp op = wct.getHierarchyOps().get(i);
diff --git a/libs/hwui/jni/Graphics.cpp b/libs/hwui/jni/Graphics.cpp
index 8315c4c..07e97f8 100644
--- a/libs/hwui/jni/Graphics.cpp
+++ b/libs/hwui/jni/Graphics.cpp
@@ -211,11 +211,7 @@
static jfieldID gRegion_nativeInstanceID;
static jmethodID gRegion_constructorMethodID;
-static jclass gByte_class;
-static jobject gVMRuntime;
-static jclass gVMRuntime_class;
-static jmethodID gVMRuntime_newNonMovableArray;
-static jmethodID gVMRuntime_addressOf;
+static jclass gByte_class;
static jclass gColorSpace_class;
static jmethodID gColorSpace_getMethodID;
@@ -789,13 +785,6 @@
gByte_class = (jclass) env->NewGlobalRef(
env->GetStaticObjectField(c, env->GetStaticFieldID(c, "TYPE", "Ljava/lang/Class;")));
- gVMRuntime_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "dalvik/system/VMRuntime"));
- m = env->GetStaticMethodID(gVMRuntime_class, "getRuntime", "()Ldalvik/system/VMRuntime;");
- gVMRuntime = env->NewGlobalRef(env->CallStaticObjectMethod(gVMRuntime_class, m));
- gVMRuntime_newNonMovableArray = GetMethodIDOrDie(env, gVMRuntime_class, "newNonMovableArray",
- "(Ljava/lang/Class;I)Ljava/lang/Object;");
- gVMRuntime_addressOf = GetMethodIDOrDie(env, gVMRuntime_class, "addressOf", "(Ljava/lang/Object;)J");
-
gColorSpace_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/ColorSpace"));
gColorSpace_getMethodID = GetStaticMethodIDOrDie(env, gColorSpace_class,
"get", "(Landroid/graphics/ColorSpace$Named;)Landroid/graphics/ColorSpace;");
diff --git a/libs/hwui/jni/android_graphics_Matrix.cpp b/libs/hwui/jni/android_graphics_Matrix.cpp
index ca667b0..c0d791a 100644
--- a/libs/hwui/jni/android_graphics_Matrix.cpp
+++ b/libs/hwui/jni/android_graphics_Matrix.cpp
@@ -376,11 +376,24 @@
{"nEquals", "(JJ)Z", (void*) SkMatrixGlue::equals}
};
+static const JNINativeMethod extra_methods[] = {
+ {"nGetNativeFinalizer", "()J", (void*)SkMatrixGlue::getNativeFinalizer},
+ {"nCreate", "(J)J", (void*)SkMatrixGlue::create},
+};
+
static jclass sClazz;
static jfieldID sNativeInstanceField;
static jmethodID sCtor;
int register_android_graphics_Matrix(JNIEnv* env) {
+ // Methods only used on Ravenwood (for now). See the javadoc on Matrix$ExtraNativesx
+ // for why we need it.
+ //
+ // We don't need it on non-ravenwood, but we don't (yet) have a way to detect ravenwood
+ // environment, so we just always run it.
+ RegisterMethodsOrDie(env, "android/graphics/Matrix$ExtraNatives", extra_methods,
+ NELEM(extra_methods));
+
int result = RegisterMethodsOrDie(env, "android/graphics/Matrix", methods, NELEM(methods));
jclass clazz = FindClassOrDie(env, "android/graphics/Matrix");
diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp
index f9dc5fa..f97992f 100644
--- a/libs/input/PointerController.cpp
+++ b/libs/input/PointerController.cpp
@@ -24,7 +24,6 @@
#include <SkColor.h>
#include <android-base/stringprintf.h>
#include <android-base/thread_annotations.h>
-#include <com_android_input_flags.h>
#include <ftl/enum.h>
#include <mutex>
@@ -35,14 +34,10 @@
#define INDENT2 " "
#define INDENT3 " "
-namespace input_flags = com::android::input::flags;
-
namespace android {
namespace {
-static const bool ENABLE_POINTER_CHOREOGRAPHER = input_flags::enable_pointer_choreographer();
-
const ui::Transform kIdentityTransform;
} // namespace
@@ -68,27 +63,24 @@
std::shared_ptr<PointerController> PointerController::create(
const sp<PointerControllerPolicyInterface>& policy, const sp<Looper>& looper,
- SpriteController& spriteController, bool enabled, ControllerType type) {
+ SpriteController& spriteController, ControllerType type) {
// using 'new' to access non-public constructor
std::shared_ptr<PointerController> controller;
switch (type) {
case ControllerType::MOUSE:
controller = std::shared_ptr<PointerController>(
- new MousePointerController(policy, looper, spriteController, enabled));
+ new MousePointerController(policy, looper, spriteController));
break;
case ControllerType::TOUCH:
controller = std::shared_ptr<PointerController>(
- new TouchPointerController(policy, looper, spriteController, enabled));
+ new TouchPointerController(policy, looper, spriteController));
break;
case ControllerType::STYLUS:
controller = std::shared_ptr<PointerController>(
- new StylusPointerController(policy, looper, spriteController, enabled));
+ new StylusPointerController(policy, looper, spriteController));
break;
- case ControllerType::LEGACY:
default:
- controller = std::shared_ptr<PointerController>(
- new PointerController(policy, looper, spriteController, enabled));
- break;
+ LOG_ALWAYS_FATAL("Invalid ControllerType: %d", static_cast<int>(type));
}
/*
@@ -108,10 +100,9 @@
}
PointerController::PointerController(const sp<PointerControllerPolicyInterface>& policy,
- const sp<Looper>& looper, SpriteController& spriteController,
- bool enabled)
+ const sp<Looper>& looper, SpriteController& spriteController)
: PointerController(
- policy, looper, spriteController, enabled,
+ policy, looper, spriteController,
[](const sp<android::gui::WindowInfosListener>& listener) {
auto initialInfo = std::make_pair(std::vector<android::gui::WindowInfo>{},
std::vector<android::gui::DisplayInfo>{});
@@ -125,11 +116,9 @@
PointerController::PointerController(const sp<PointerControllerPolicyInterface>& policy,
const sp<Looper>& looper, SpriteController& spriteController,
- bool enabled,
const WindowListenerRegisterConsumer& registerListener,
WindowListenerUnregisterConsumer unregisterListener)
- : mEnabled(enabled),
- mContext(policy, looper, spriteController, *this),
+ : mContext(policy, looper, spriteController, *this),
mCursorController(mContext),
mDisplayInfoListener(sp<DisplayInfoListener>::make(this)),
mUnregisterWindowInfosListener(std::move(unregisterListener)) {
@@ -142,7 +131,6 @@
PointerController::~PointerController() {
mDisplayInfoListener->onPointerControllerDestroyed();
mUnregisterWindowInfosListener(mDisplayInfoListener);
- mContext.getPolicy()->onPointerDisplayIdChanged(ADISPLAY_ID_NONE, FloatPoint{0, 0});
}
std::mutex& PointerController::getLock() const {
@@ -150,14 +138,10 @@
}
std::optional<FloatRect> PointerController::getBounds() const {
- if (!mEnabled) return {};
-
return mCursorController.getBounds();
}
void PointerController::move(float deltaX, float deltaY) {
- if (!mEnabled) return;
-
const int32_t displayId = mCursorController.getDisplayId();
vec2 transformed;
{
@@ -169,8 +153,6 @@
}
void PointerController::setPosition(float x, float y) {
- if (!mEnabled) return;
-
const int32_t displayId = mCursorController.getDisplayId();
vec2 transformed;
{
@@ -182,10 +164,6 @@
}
FloatPoint PointerController::getPosition() const {
- if (!mEnabled) {
- return FloatPoint{0, 0};
- }
-
const int32_t displayId = mCursorController.getDisplayId();
const auto p = mCursorController.getPosition();
{
@@ -196,28 +174,20 @@
}
int32_t PointerController::getDisplayId() const {
- if (!mEnabled) return ADISPLAY_ID_NONE;
-
return mCursorController.getDisplayId();
}
void PointerController::fade(Transition transition) {
- if (!mEnabled) return;
-
std::scoped_lock lock(getLock());
mCursorController.fade(transition);
}
void PointerController::unfade(Transition transition) {
- if (!mEnabled) return;
-
std::scoped_lock lock(getLock());
mCursorController.unfade(transition);
}
void PointerController::setPresentation(Presentation presentation) {
- if (!mEnabled) return;
-
std::scoped_lock lock(getLock());
if (mLocked.presentation == presentation) {
@@ -226,33 +196,13 @@
mLocked.presentation = presentation;
- if (ENABLE_POINTER_CHOREOGRAPHER) {
- // When pointer choreographer is enabled, the presentation mode is only set once when the
- // PointerController is constructed, before the display viewport is provided.
- // TODO(b/293587049): Clean up the PointerController interface after pointer choreographer
- // is permanently enabled. The presentation can be set in the constructor.
- mCursorController.setStylusHoverMode(presentation == Presentation::STYLUS_HOVER);
- return;
- }
-
- if (!mCursorController.isViewportValid()) {
- return;
- }
-
- if (presentation == Presentation::POINTER || presentation == Presentation::STYLUS_HOVER) {
- // For now, we support stylus hover using the mouse cursor implementation.
- // TODO: Add proper support for stylus hover icons.
- mCursorController.setStylusHoverMode(presentation == Presentation::STYLUS_HOVER);
-
- mCursorController.getAdditionalMouseResources();
- clearSpotsLocked();
- }
+ // The presentation mode is only set once when the PointerController is constructed,
+ // before the display viewport is provided.
+ mCursorController.setStylusHoverMode(presentation == Presentation::STYLUS_HOVER);
}
void PointerController::setSpots(const PointerCoords* spotCoords, const uint32_t* spotIdToIndex,
BitSet32 spotIdBits, int32_t displayId) {
- if (!mEnabled) return;
-
std::scoped_lock lock(getLock());
std::array<PointerCoords, MAX_POINTERS> outSpotCoords{};
const ui::Transform& transform = getTransformForDisplayLocked(displayId);
@@ -272,12 +222,13 @@
if (it == mLocked.spotControllers.end()) {
mLocked.spotControllers.try_emplace(displayId, displayId, mContext);
}
- mLocked.spotControllers.at(displayId).setSpots(outSpotCoords.data(), spotIdToIndex, spotIdBits);
+ bool skipScreenshot = mLocked.displaysToSkipScreenshot.find(displayId) !=
+ mLocked.displaysToSkipScreenshot.end();
+ mLocked.spotControllers.at(displayId).setSpots(outSpotCoords.data(), spotIdToIndex, spotIdBits,
+ skipScreenshot);
}
void PointerController::clearSpots() {
- if (!mEnabled) return;
-
std::scoped_lock lock(getLock());
clearSpotsLocked();
}
@@ -310,12 +261,6 @@
}
void PointerController::setDisplayViewport(const DisplayViewport& viewport) {
- struct PointerDisplayChangeArgs {
- int32_t displayId;
- FloatPoint cursorPosition;
- };
- std::optional<PointerDisplayChangeArgs> pointerDisplayChanged;
-
{ // acquire lock
std::scoped_lock lock(getLock());
@@ -327,31 +272,29 @@
mCursorController.setDisplayViewport(viewport, getAdditionalMouseResources);
if (viewport.displayId != mLocked.pointerDisplayId) {
mLocked.pointerDisplayId = viewport.displayId;
- pointerDisplayChanged = {viewport.displayId, mCursorController.getPosition()};
}
} // release lock
-
- if (pointerDisplayChanged) {
- // Notify the policy without holding the pointer controller lock.
- mContext.getPolicy()->onPointerDisplayIdChanged(pointerDisplayChanged->displayId,
- pointerDisplayChanged->cursorPosition);
- }
}
void PointerController::updatePointerIcon(PointerIconStyle iconId) {
- if (!mEnabled) return;
-
std::scoped_lock lock(getLock());
mCursorController.updatePointerIcon(iconId);
}
void PointerController::setCustomPointerIcon(const SpriteIcon& icon) {
- if (!mEnabled) return;
-
std::scoped_lock lock(getLock());
mCursorController.setCustomPointerIcon(icon);
}
+void PointerController::setSkipScreenshot(int32_t displayId, bool skip) {
+ std::scoped_lock lock(getLock());
+ if (skip) {
+ mLocked.displaysToSkipScreenshot.insert(displayId);
+ } else {
+ mLocked.displaysToSkipScreenshot.erase(displayId);
+ }
+}
+
void PointerController::doInactivityTimeout() {
fade(Transition::GRADUAL);
}
@@ -392,10 +335,6 @@
}
std::string PointerController::dump() {
- if (!mEnabled) {
- return INDENT "PointerController: DISABLED due to ongoing PointerChoreographer refactor\n";
- }
-
std::string dump = INDENT "PointerController:\n";
std::scoped_lock lock(getLock());
dump += StringPrintf(INDENT2 "Presentation: %s\n",
@@ -416,8 +355,8 @@
MousePointerController::MousePointerController(const sp<PointerControllerPolicyInterface>& policy,
const sp<Looper>& looper,
- SpriteController& spriteController, bool enabled)
- : PointerController(policy, looper, spriteController, enabled) {
+ SpriteController& spriteController)
+ : PointerController(policy, looper, spriteController) {
PointerController::setPresentation(Presentation::POINTER);
}
@@ -429,8 +368,8 @@
TouchPointerController::TouchPointerController(const sp<PointerControllerPolicyInterface>& policy,
const sp<Looper>& looper,
- SpriteController& spriteController, bool enabled)
- : PointerController(policy, looper, spriteController, enabled) {
+ SpriteController& spriteController)
+ : PointerController(policy, looper, spriteController) {
PointerController::setPresentation(Presentation::SPOT);
}
@@ -442,8 +381,8 @@
StylusPointerController::StylusPointerController(const sp<PointerControllerPolicyInterface>& policy,
const sp<Looper>& looper,
- SpriteController& spriteController, bool enabled)
- : PointerController(policy, looper, spriteController, enabled) {
+ SpriteController& spriteController)
+ : PointerController(policy, looper, spriteController) {
PointerController::setPresentation(Presentation::STYLUS_HOVER);
}
diff --git a/libs/input/PointerController.h b/libs/input/PointerController.h
index 6ee5707..eaf34d5 100644
--- a/libs/input/PointerController.h
+++ b/libs/input/PointerController.h
@@ -47,8 +47,7 @@
public:
static std::shared_ptr<PointerController> create(
const sp<PointerControllerPolicyInterface>& policy, const sp<Looper>& looper,
- SpriteController& spriteController, bool enabled,
- ControllerType type = ControllerType::LEGACY);
+ SpriteController& spriteController, ControllerType type);
~PointerController() override;
@@ -67,6 +66,7 @@
void clearSpots() override;
void updatePointerIcon(PointerIconStyle iconId) override;
void setCustomPointerIcon(const SpriteIcon& icon) override;
+ void setSkipScreenshot(int32_t displayId, bool skip) override;
virtual void setInactivityTimeout(InactivityTimeout inactivityTimeout);
void doInactivityTimeout();
@@ -86,12 +86,12 @@
// Constructor used to test WindowInfosListener registration.
PointerController(const sp<PointerControllerPolicyInterface>& policy, const sp<Looper>& looper,
- SpriteController& spriteController, bool enabled,
+ SpriteController& spriteController,
const WindowListenerRegisterConsumer& registerListener,
WindowListenerUnregisterConsumer unregisterListener);
PointerController(const sp<PointerControllerPolicyInterface>& policy, const sp<Looper>& looper,
- SpriteController& spriteController, bool enabled);
+ SpriteController& spriteController);
private:
friend PointerControllerContext::LooperCallback;
@@ -103,8 +103,6 @@
// we use the DisplayInfoListener's lock in PointerController.
std::mutex& getLock() const;
- const bool mEnabled;
-
PointerControllerContext mContext;
MouseCursorController mCursorController;
@@ -115,6 +113,7 @@
std::vector<gui::DisplayInfo> mDisplayInfos;
std::unordered_map<int32_t /* displayId */, TouchSpotController> spotControllers;
+ std::unordered_set<int32_t /* displayId */> displaysToSkipScreenshot;
} mLocked GUARDED_BY(getLock());
class DisplayInfoListener : public gui::WindowInfosListener {
@@ -142,8 +141,7 @@
public:
/** A version of PointerController that controls one mouse pointer. */
MousePointerController(const sp<PointerControllerPolicyInterface>& policy,
- const sp<Looper>& looper, SpriteController& spriteController,
- bool enabled);
+ const sp<Looper>& looper, SpriteController& spriteController);
~MousePointerController() override;
@@ -162,8 +160,7 @@
public:
/** A version of PointerController that controls touch spots. */
TouchPointerController(const sp<PointerControllerPolicyInterface>& policy,
- const sp<Looper>& looper, SpriteController& spriteController,
- bool enabled);
+ const sp<Looper>& looper, SpriteController& spriteController);
~TouchPointerController() override;
@@ -208,8 +205,7 @@
public:
/** A version of PointerController that controls one stylus pointer. */
StylusPointerController(const sp<PointerControllerPolicyInterface>& policy,
- const sp<Looper>& looper, SpriteController& spriteController,
- bool enabled);
+ const sp<Looper>& looper, SpriteController& spriteController);
~StylusPointerController() override;
diff --git a/libs/input/PointerControllerContext.h b/libs/input/PointerControllerContext.h
index 98c3988..e893c49 100644
--- a/libs/input/PointerControllerContext.h
+++ b/libs/input/PointerControllerContext.h
@@ -81,7 +81,6 @@
virtual PointerIconStyle getDefaultPointerIconId() = 0;
virtual PointerIconStyle getDefaultStylusIconId() = 0;
virtual PointerIconStyle getCustomPointerIconId() = 0;
- virtual void onPointerDisplayIdChanged(int32_t displayId, const FloatPoint& position) = 0;
};
/*
diff --git a/libs/input/SpriteController.cpp b/libs/input/SpriteController.cpp
index a63453d..0baa929 100644
--- a/libs/input/SpriteController.cpp
+++ b/libs/input/SpriteController.cpp
@@ -129,7 +129,7 @@
update.state.surfaceVisible = false;
update.state.surfaceControl =
obtainSurface(update.state.surfaceWidth, update.state.surfaceHeight,
- update.state.displayId);
+ update.state.displayId, update.state.skipScreenshot);
if (update.state.surfaceControl != NULL) {
update.surfaceChanged = surfaceChanged = true;
}
@@ -209,7 +209,7 @@
(update.state.dirty &
(DIRTY_ALPHA | DIRTY_POSITION | DIRTY_TRANSFORMATION_MATRIX | DIRTY_LAYER |
DIRTY_VISIBILITY | DIRTY_HOTSPOT | DIRTY_DISPLAY_ID | DIRTY_ICON_STYLE |
- DIRTY_DRAW_DROP_SHADOW))))) {
+ DIRTY_DRAW_DROP_SHADOW | DIRTY_SKIP_SCREENSHOT))))) {
needApplyTransaction = true;
if (wantSurfaceVisibleAndDrawn
@@ -260,6 +260,14 @@
t.setLayer(update.state.surfaceControl, surfaceLayer);
}
+ if (wantSurfaceVisibleAndDrawn &&
+ (becomingVisible || (update.state.dirty & DIRTY_SKIP_SCREENSHOT))) {
+ int32_t flags =
+ update.state.skipScreenshot ? ISurfaceComposerClient::eSkipScreenshot : 0;
+ t.setFlags(update.state.surfaceControl, flags,
+ ISurfaceComposerClient::eSkipScreenshot);
+ }
+
if (becomingVisible) {
t.show(update.state.surfaceControl);
@@ -332,8 +340,8 @@
}
}
-sp<SurfaceControl> SpriteController::obtainSurface(int32_t width, int32_t height,
- int32_t displayId) {
+sp<SurfaceControl> SpriteController::obtainSurface(int32_t width, int32_t height, int32_t displayId,
+ bool hideOnMirrored) {
ensureSurfaceComposerClient();
const sp<SurfaceControl> parent = mParentSurfaceProvider(displayId);
@@ -341,11 +349,13 @@
ALOGE("Failed to get the parent surface for pointers on display %d", displayId);
}
+ int32_t createFlags = ISurfaceComposerClient::eHidden | ISurfaceComposerClient::eCursorWindow;
+ if (hideOnMirrored) {
+ createFlags |= ISurfaceComposerClient::eSkipScreenshot;
+ }
const sp<SurfaceControl> surfaceControl =
mSurfaceComposerClient->createSurface(String8("Sprite"), width, height,
- PIXEL_FORMAT_RGBA_8888,
- ISurfaceComposerClient::eHidden |
- ISurfaceComposerClient::eCursorWindow,
+ PIXEL_FORMAT_RGBA_8888, createFlags,
parent ? parent->getHandle() : nullptr);
if (surfaceControl == nullptr || !surfaceControl->isValid()) {
ALOGE("Error creating sprite surface.");
@@ -474,6 +484,15 @@
}
}
+void SpriteController::SpriteImpl::setSkipScreenshot(bool skip) {
+ AutoMutex _l(mController.mLock);
+
+ if (mLocked.state.skipScreenshot != skip) {
+ mLocked.state.skipScreenshot = skip;
+ invalidateLocked(DIRTY_SKIP_SCREENSHOT);
+ }
+}
+
void SpriteController::SpriteImpl::invalidateLocked(uint32_t dirty) {
bool wasDirty = mLocked.state.dirty;
mLocked.state.dirty |= dirty;
diff --git a/libs/input/SpriteController.h b/libs/input/SpriteController.h
index 35776e9..4e4ba65 100644
--- a/libs/input/SpriteController.h
+++ b/libs/input/SpriteController.h
@@ -96,6 +96,10 @@
/* Sets the id of the display where the sprite should be shown. */
virtual void setDisplayId(int32_t displayId) = 0;
+
+ /* Sets the flag to hide sprite on mirrored displays.
+ * This will add ISurfaceComposerClient::eSkipScreenshot flag to the sprite. */
+ virtual void setSkipScreenshot(bool skip) = 0;
};
/*
@@ -152,6 +156,7 @@
DIRTY_DISPLAY_ID = 1 << 7,
DIRTY_ICON_STYLE = 1 << 8,
DIRTY_DRAW_DROP_SHADOW = 1 << 9,
+ DIRTY_SKIP_SCREENSHOT = 1 << 10,
};
/* Describes the state of a sprite.
@@ -182,6 +187,7 @@
int32_t surfaceHeight;
bool surfaceDrawn;
bool surfaceVisible;
+ bool skipScreenshot;
inline bool wantSurfaceVisible() const {
return visible && alpha > 0.0f && icon.isValid();
@@ -209,6 +215,7 @@
virtual void setAlpha(float alpha);
virtual void setTransformationMatrix(const SpriteTransformationMatrix& matrix);
virtual void setDisplayId(int32_t displayId);
+ virtual void setSkipScreenshot(bool skip);
inline const SpriteState& getStateLocked() const {
return mLocked.state;
@@ -272,7 +279,8 @@
void doDisposeSurfaces();
void ensureSurfaceComposerClient();
- sp<SurfaceControl> obtainSurface(int32_t width, int32_t height, int32_t displayId);
+ sp<SurfaceControl> obtainSurface(int32_t width, int32_t height, int32_t displayId,
+ bool hideOnMirrored);
};
} // namespace android
diff --git a/libs/input/TouchSpotController.cpp b/libs/input/TouchSpotController.cpp
index 99952aa..530d541 100644
--- a/libs/input/TouchSpotController.cpp
+++ b/libs/input/TouchSpotController.cpp
@@ -40,12 +40,13 @@
// --- Spot ---
void TouchSpotController::Spot::updateSprite(const SpriteIcon* icon, float newX, float newY,
- int32_t displayId) {
+ int32_t displayId, bool skipScreenshot) {
sprite->setLayer(Sprite::BASE_LAYER_SPOT + id);
sprite->setAlpha(alpha);
sprite->setTransformationMatrix(SpriteTransformationMatrix(scale, 0.0f, 0.0f, scale));
sprite->setPosition(newX, newY);
sprite->setDisplayId(displayId);
+ sprite->setSkipScreenshot(skipScreenshot);
x = newX;
y = newY;
@@ -84,7 +85,7 @@
}
void TouchSpotController::setSpots(const PointerCoords* spotCoords, const uint32_t* spotIdToIndex,
- BitSet32 spotIdBits) {
+ BitSet32 spotIdBits, bool skipScreenshot) {
#if DEBUG_SPOT_UPDATES
ALOGD("setSpots: idBits=%08x", spotIdBits.value);
for (BitSet32 idBits(spotIdBits); !idBits.isEmpty();) {
@@ -116,7 +117,7 @@
spot = createAndAddSpotLocked(id, mLocked.displaySpots);
}
- spot->updateSprite(&icon, x, y, mDisplayId);
+ spot->updateSprite(&icon, x, y, mDisplayId, skipScreenshot);
}
for (Spot* spot : mLocked.displaySpots) {
diff --git a/libs/input/TouchSpotController.h b/libs/input/TouchSpotController.h
index 5bbc75d..608653c 100644
--- a/libs/input/TouchSpotController.h
+++ b/libs/input/TouchSpotController.h
@@ -32,7 +32,7 @@
TouchSpotController(int32_t displayId, PointerControllerContext& context);
~TouchSpotController();
void setSpots(const PointerCoords* spotCoords, const uint32_t* spotIdToIndex,
- BitSet32 spotIdBits);
+ BitSet32 spotIdBits, bool skipScreenshot);
void clearSpots();
void reloadSpotResources();
@@ -59,7 +59,8 @@
y(0.0f),
mLastIcon(nullptr) {}
- void updateSprite(const SpriteIcon* icon, float x, float y, int32_t displayId);
+ void updateSprite(const SpriteIcon* icon, float x, float y, int32_t displayId,
+ bool skipScreenshot);
void dump(std::string& out, const char* prefix = "") const;
private:
diff --git a/libs/input/tests/PointerController_test.cpp b/libs/input/tests/PointerController_test.cpp
index a1bb5b3..3bc0e24 100644
--- a/libs/input/tests/PointerController_test.cpp
+++ b/libs/input/tests/PointerController_test.cpp
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-#include <com_android_input_flags.h>
#include <flag_macros.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
@@ -30,8 +29,6 @@
namespace android {
-namespace input_flags = com::android::input::flags;
-
enum TestCursorType {
CURSOR_TYPE_DEFAULT = 0,
CURSOR_TYPE_HOVER,
@@ -64,11 +61,9 @@
virtual PointerIconStyle getDefaultPointerIconId() override;
virtual PointerIconStyle getDefaultStylusIconId() override;
virtual PointerIconStyle getCustomPointerIconId() override;
- virtual void onPointerDisplayIdChanged(int32_t displayId, const FloatPoint& position) override;
bool allResourcesAreLoaded();
bool noResourcesAreLoaded();
- std::optional<int32_t> getLastReportedPointerDisplayId() { return latestPointerDisplayId; }
private:
void loadPointerIconForType(SpriteIcon* icon, int32_t cursorType);
@@ -76,7 +71,6 @@
bool pointerIconLoaded{false};
bool pointerResourcesLoaded{false};
bool additionalMouseResourcesLoaded{false};
- std::optional<int32_t /*displayId*/> latestPointerDisplayId;
};
void MockPointerControllerPolicyInterface::loadPointerIcon(SpriteIcon* icon, int32_t) {
@@ -146,12 +140,6 @@
icon->hotSpotY = hotSpot.second;
}
-void MockPointerControllerPolicyInterface::onPointerDisplayIdChanged(int32_t displayId,
- const FloatPoint& /*position*/
-) {
- latestPointerDisplayId = displayId;
-}
-
class TestPointerController : public PointerController {
public:
TestPointerController(sp<android::gui::WindowInfosListener>& registeredListener,
@@ -159,7 +147,6 @@
SpriteController& spriteController)
: PointerController(
policy, looper, spriteController,
- /*enabled=*/true,
[®isteredListener](const sp<android::gui::WindowInfosListener>& listener)
-> std::vector<gui::DisplayInfo> {
// Register listener
@@ -267,8 +254,7 @@
mPointerController->reloadPointerResources();
}
-TEST_F_WITH_FLAGS(PointerControllerTest, setPresentationBeforeDisplayViewportDoesNotLoadResources,
- REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(input_flags, enable_pointer_choreographer))) {
+TEST_F(PointerControllerTest, setPresentationBeforeDisplayViewportDoesNotLoadResources) {
// Setting the presentation mode before a display viewport is set will not load any resources.
mPointerController->setPresentation(PointerController::Presentation::POINTER);
ASSERT_TRUE(mPolicy->noResourcesAreLoaded());
@@ -278,26 +264,7 @@
ASSERT_TRUE(mPolicy->allResourcesAreLoaded());
}
-TEST_F_WITH_FLAGS(PointerControllerTest, updatePointerIcon,
- REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(input_flags,
- enable_pointer_choreographer))) {
- ensureDisplayViewportIsSet();
- mPointerController->setPresentation(PointerController::Presentation::POINTER);
- mPointerController->unfade(PointerController::Transition::IMMEDIATE);
-
- int32_t type = CURSOR_TYPE_ADDITIONAL;
- std::pair<float, float> hotspot = getHotSpotCoordinatesForType(type);
- EXPECT_CALL(*mPointerSprite, setVisible(true));
- EXPECT_CALL(*mPointerSprite, setAlpha(1.0f));
- EXPECT_CALL(*mPointerSprite,
- setIcon(AllOf(Field(&SpriteIcon::style, static_cast<PointerIconStyle>(type)),
- Field(&SpriteIcon::hotSpotX, hotspot.first),
- Field(&SpriteIcon::hotSpotY, hotspot.second))));
- mPointerController->updatePointerIcon(static_cast<PointerIconStyle>(type));
-}
-
-TEST_F_WITH_FLAGS(PointerControllerTest, updatePointerIconWithChoreographer,
- REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(input_flags, enable_pointer_choreographer))) {
+TEST_F(PointerControllerTest, updatePointerIconWithChoreographer) {
// When PointerChoreographer is enabled, the presentation mode is set before the viewport.
mPointerController->setPresentation(PointerController::Presentation::POINTER);
ensureDisplayViewportIsSet();
@@ -348,28 +315,43 @@
ensureDisplayViewportIsSet();
}
-TEST_F(PointerControllerTest, notifiesPolicyWhenPointerDisplayChanges) {
- EXPECT_FALSE(mPolicy->getLastReportedPointerDisplayId())
- << "A pointer display change does not occur when PointerController is created.";
+TEST_F(PointerControllerTest, updatesSkipScreenshotFlagForTouchSpots) {
+ ensureDisplayViewportIsSet();
- ensureDisplayViewportIsSet(ADISPLAY_ID_DEFAULT);
+ PointerCoords testSpotCoords;
+ testSpotCoords.clear();
+ testSpotCoords.setAxisValue(AMOTION_EVENT_AXIS_X, 1);
+ testSpotCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, 1);
+ BitSet32 testIdBits;
+ testIdBits.markBit(0);
+ std::array<uint32_t, MAX_POINTER_ID + 1> testIdToIndex;
- const auto lastReportedPointerDisplayId = mPolicy->getLastReportedPointerDisplayId();
- ASSERT_TRUE(lastReportedPointerDisplayId)
- << "The policy is notified of a pointer display change when the viewport is first set.";
- EXPECT_EQ(ADISPLAY_ID_DEFAULT, *lastReportedPointerDisplayId)
- << "Incorrect pointer display notified.";
+ sp<MockSprite> testSpotSprite(new NiceMock<MockSprite>);
- ensureDisplayViewportIsSet(42);
+ // By default sprite is not marked secure
+ EXPECT_CALL(*mSpriteController, createSprite).WillOnce(Return(testSpotSprite));
+ EXPECT_CALL(*testSpotSprite, setSkipScreenshot).With(testing::Args<0>(false));
- EXPECT_EQ(42, *mPolicy->getLastReportedPointerDisplayId())
- << "The policy is notified when the pointer display changes.";
+ // Update spots to sync state with sprite
+ mPointerController->setSpots(&testSpotCoords, testIdToIndex.cbegin(), testIdBits,
+ ADISPLAY_ID_DEFAULT);
+ testing::Mock::VerifyAndClearExpectations(testSpotSprite.get());
- // Release the PointerController.
- mPointerController = nullptr;
+ // Marking the display to skip screenshot should update sprite as well
+ mPointerController->setSkipScreenshot(ADISPLAY_ID_DEFAULT, true);
+ EXPECT_CALL(*testSpotSprite, setSkipScreenshot).With(testing::Args<0>(true));
- EXPECT_EQ(ADISPLAY_ID_NONE, *mPolicy->getLastReportedPointerDisplayId())
- << "The pointer display changes to invalid when PointerController is destroyed.";
+ // Update spots to sync state with sprite
+ mPointerController->setSpots(&testSpotCoords, testIdToIndex.cbegin(), testIdBits,
+ ADISPLAY_ID_DEFAULT);
+ testing::Mock::VerifyAndClearExpectations(testSpotSprite.get());
+
+ // Reset flag and verify again
+ mPointerController->setSkipScreenshot(ADISPLAY_ID_DEFAULT, false);
+ EXPECT_CALL(*testSpotSprite, setSkipScreenshot).With(testing::Args<0>(false));
+ mPointerController->setSpots(&testSpotCoords, testIdToIndex.cbegin(), testIdBits,
+ ADISPLAY_ID_DEFAULT);
+ testing::Mock::VerifyAndClearExpectations(testSpotSprite.get());
}
class PointerControllerWindowInfoListenerTest : public Test {};
diff --git a/libs/input/tests/mocks/MockSprite.h b/libs/input/tests/mocks/MockSprite.h
index 013b79c..0867221 100644
--- a/libs/input/tests/mocks/MockSprite.h
+++ b/libs/input/tests/mocks/MockSprite.h
@@ -34,6 +34,7 @@
MOCK_METHOD(void, setAlpha, (float), (override));
MOCK_METHOD(void, setTransformationMatrix, (const SpriteTransformationMatrix&), (override));
MOCK_METHOD(void, setDisplayId, (int32_t), (override));
+ MOCK_METHOD(void, setSkipScreenshot, (bool), (override));
};
} // namespace android
diff --git a/location/lib/java/com/android/location/provider/SignificantPlaceProvider.java b/location/lib/java/com/android/location/provider/SignificantPlaceProvider.java
new file mode 100644
index 0000000..0b39a9a
--- /dev/null
+++ b/location/lib/java/com/android/location/provider/SignificantPlaceProvider.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.location.provider;
+
+import android.annotation.Nullable;
+import android.app.trust.TrustManager;
+import android.hardware.location.ISignificantPlaceProvider;
+import android.hardware.location.ISignificantPlaceProviderManager;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.Process;
+import android.os.RemoteException;
+
+import com.android.internal.annotations.GuardedBy;
+
+/** @hide */
+public class SignificantPlaceProvider {
+
+ public static final String ACTION = TrustManager.ACTION_BIND_SIGNIFICANT_PLACE_PROVIDER;
+
+ private final IBinder mBinder;
+
+ // write locked on mBinder, read lock is optional depending on atomicity requirements
+ @Nullable private volatile ISignificantPlaceProviderManager mManager;
+
+ @GuardedBy("mBinder")
+ private boolean mInSignificantPlace = false;
+
+ public SignificantPlaceProvider() {
+ mBinder = new Service();
+ mManager = null;
+ }
+
+ public IBinder getBinder() {
+ return mBinder;
+ }
+
+ /** Set whether the device is currently in a trusted location. */
+ public void setInSignificantPlace(boolean inSignificantPlace) {
+ synchronized (mBinder) {
+ if (inSignificantPlace == mInSignificantPlace) {
+ return;
+ }
+
+ mInSignificantPlace = inSignificantPlace;
+ }
+
+ ISignificantPlaceProviderManager manager = mManager;
+ if (manager != null) {
+ try {
+ manager.setInSignificantPlace(inSignificantPlace);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+
+ private final class Service extends ISignificantPlaceProvider.Stub {
+
+ Service() {}
+
+ @Override
+ public void setSignificantPlaceProviderManager(ISignificantPlaceProviderManager manager) {
+ if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+ return;
+ }
+
+ synchronized (mBinder) {
+ if (mInSignificantPlace) {
+ try {
+ manager.setInSignificantPlace(true);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ mManager = manager;
+ }
+ }
+ }
+}
diff --git a/media/OWNERS b/media/OWNERS
index 1e5a458..5e39195 100644
--- a/media/OWNERS
+++ b/media/OWNERS
@@ -11,6 +11,7 @@
nchalko@google.com
philburk@google.com
quxiangfang@google.com
+shuzhenwang@google.com
wonsik@google.com
# go/android-fwk-media-solutions for info on areas of ownership.
diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java
index 554fe5e..b2838c8 100644
--- a/media/java/android/media/MediaRouter2.java
+++ b/media/java/android/media/MediaRouter2.java
@@ -2064,24 +2064,31 @@
}
/**
- * Transfers to a given route for the remote session. The given route must be included in
- * {@link RoutingSessionInfo#getTransferableRoutes()}.
+ * Attempts a transfer to a {@link RoutingSessionInfo#getTransferableRoutes() transferable
+ * route}.
*
+ * <p>Transferring to a transferable route does not require the app to transfer the playback
+ * state from one route to the other. The route provider completely manages the transfer. An
+ * example of provider-managed transfers are the switches between the system's routes, like
+ * the built-in speakers and a BT headset.
+ *
+ * @return True if the transfer is handled by this controller, or false if a new controller
+ * should be created instead.
* @see RoutingSessionInfo#getSelectedRoutes()
* @see RoutingSessionInfo#getTransferableRoutes()
* @see ControllerCallback#onControllerUpdated
*/
- void transferToRoute(@NonNull MediaRoute2Info route) {
+ boolean tryTransferWithinProvider(@NonNull MediaRoute2Info route) {
Objects.requireNonNull(route, "route must not be null");
synchronized (mControllerLock) {
if (isReleased()) {
Log.w(TAG, "transferToRoute: Called on released controller. Ignoring.");
- return;
+ return true;
}
if (!mSessionInfo.getTransferableRoutes().contains(route.getId())) {
Log.w(TAG, "Ignoring transferring to a non-transferable route=" + route);
- return;
+ return false;
}
}
@@ -2096,6 +2103,7 @@
Log.e(TAG, "Unable to transfer to route for session.", ex);
}
}
+ return true;
}
/**
@@ -3587,20 +3595,14 @@
}
RoutingController controller = getCurrentController();
- if (controller
- .getRoutingSessionInfo()
- .getTransferableRoutes()
- .contains(route.getId())) {
- controller.transferToRoute(route);
- return;
+ if (!controller.tryTransferWithinProvider(route)) {
+ requestCreateController(
+ controller,
+ route,
+ MANAGER_REQUEST_ID_NONE,
+ Process.myUserHandle(),
+ mContext.getPackageName());
}
-
- requestCreateController(
- controller,
- route,
- MANAGER_REQUEST_ID_NONE,
- Process.myUserHandle(),
- mContext.getPackageName());
}
@Override
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/OWNERS b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/OWNERS
new file mode 100644
index 0000000..f4f9c08
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 1344
+include platform/frameworks/base:/media/OWNERS
+
+# Camera
+per-file *Camera* = file:platform/frameworks/av:/camera/OWNERS
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
index fc96896..353366d 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
@@ -89,7 +89,8 @@
public void testCameraInfo() throws Exception {
for (int cameraId = 0; cameraId < mUtils.getGuessedNumCameras(); ++cameraId) {
CameraInfo info = mUtils.getCameraService().getCameraInfo(cameraId,
- /*overrideToPortrait*/false, DEVICE_ID_DEFAULT, DEVICE_POLICY_DEFAULT);
+ ICameraService.ROTATION_OVERRIDE_NONE, DEVICE_ID_DEFAULT,
+ DEVICE_POLICY_DEFAULT);
assertTrue("Facing was not set for camera " + cameraId, info.info.facing != -1);
assertTrue("Orientation was not set for camera " + cameraId,
info.info.orientation != -1);
@@ -164,7 +165,7 @@
ICameraService.USE_CALLING_UID,
ICameraService.USE_CALLING_PID,
getContext().getApplicationInfo().targetSdkVersion,
- /*overrideToPortrait*/false,
+ ICameraService.ROTATION_OVERRIDE_NONE,
/*forceSlowJpegMode*/false,
DEVICE_ID_DEFAULT, DEVICE_POLICY_DEFAULT);
assertNotNull(String.format("Camera %s was null", cameraId), cameraUser);
@@ -266,7 +267,8 @@
clientPackageName, clientAttributionTag,
ICameraService.USE_CALLING_UID, 0 /*oomScoreOffset*/,
getContext().getApplicationInfo().targetSdkVersion,
- /*overrideToPortrait*/false, DEVICE_ID_DEFAULT, DEVICE_POLICY_DEFAULT);
+ ICameraService.ROTATION_OVERRIDE_NONE, DEVICE_ID_DEFAULT,
+ DEVICE_POLICY_DEFAULT);
assertNotNull(String.format("Camera %s was null", cameraId), cameraUser);
Log.v(TAG, String.format("Camera %s connected", cameraId));
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
index dc8647f..6cf2a41 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
@@ -248,7 +248,7 @@
mCameraUser = mUtils.getCameraService().connectDevice(mMockCb, mCameraId,
clientPackageName, clientAttributionTag, ICameraService.USE_CALLING_UID,
/*oomScoreOffset*/0, getContext().getApplicationInfo().targetSdkVersion,
- /*overrideToPortrait*/false, DEVICE_ID_DEFAULT, DEVICE_POLICY_DEFAULT);
+ ICameraService.ROTATION_OVERRIDE_NONE, DEVICE_ID_DEFAULT, DEVICE_POLICY_DEFAULT);
assertNotNull(String.format("Camera %s was null", mCameraId), mCameraUser);
mHandlerThread = new HandlerThread(TAG);
mHandlerThread.start();
@@ -415,7 +415,8 @@
@SmallTest
public void testCameraCharacteristics() throws RemoteException {
CameraMetadataNative info = mUtils.getCameraService().getCameraCharacteristics(mCameraId,
- getContext().getApplicationInfo().targetSdkVersion, /*overrideToPortrait*/false,
+ getContext().getApplicationInfo().targetSdkVersion,
+ ICameraService.ROTATION_OVERRIDE_NONE,
DEVICE_ID_DEFAULT, DEVICE_POLICY_DEFAULT);
assertFalse(info.isEmpty());
diff --git a/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp b/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp
index 58f56b8..78a5357 100644
--- a/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp
+++ b/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp
@@ -16,6 +16,7 @@
#define LOG_TAG "PerformanceHintNativeTest"
+#include <aidl/android/hardware/power/ChannelConfig.h>
#include <aidl/android/hardware/power/SessionConfig.h>
#include <aidl/android/hardware/power/SessionTag.h>
#include <aidl/android/hardware/power/WorkDuration.h>
@@ -54,6 +55,9 @@
MOCK_METHOD(ScopedAStatus, getHintSessionThreadIds,
(const std::shared_ptr<IHintSession>& hintSession, ::std::vector<int32_t>* tids),
(override));
+ MOCK_METHOD(ScopedAStatus, getSessionChannel,
+ (const ::ndk::SpAIBinder& in_token, hal::ChannelConfig* _aidl_return), (override));
+ MOCK_METHOD(ScopedAStatus, closeSessionChannel, (), (override));
MOCK_METHOD(SpAIBinder, asBinder, (), (override));
MOCK_METHOD(bool, isRemote, (), (override));
};
diff --git a/nfc/java/android/nfc/cardemulation/CardEmulation.java b/nfc/java/android/nfc/cardemulation/CardEmulation.java
index de9eada1..2fe2ce3 100644
--- a/nfc/java/android/nfc/cardemulation/CardEmulation.java
+++ b/nfc/java/android/nfc/cardemulation/CardEmulation.java
@@ -1212,16 +1212,16 @@
*
* @param service The ComponentName of the service
* @param status true to enable, false to disable
+ * @param userId the user handle of the user whose information is being requested.
* @return set service for the category and true if service is already set return false.
*
* @hide
*/
- public boolean setServiceEnabledForCategoryOther(ComponentName service, boolean status) {
+ public boolean setServiceEnabledForCategoryOther(ComponentName service, boolean status,
+ int userId) {
if (service == null) {
throw new NullPointerException("activity or service or category is null");
}
- int userId = mContext.getUser().getIdentifier();
-
try {
return sService.setServiceEnabledForCategoryOther(userId, service, status);
} catch (RemoteException e) {
diff --git a/nfc/java/android/nfc/cardemulation/PollingFrame.java b/nfc/java/android/nfc/cardemulation/PollingFrame.java
index b52faba..4c76fb0 100644
--- a/nfc/java/android/nfc/cardemulation/PollingFrame.java
+++ b/nfc/java/android/nfc/cardemulation/PollingFrame.java
@@ -44,8 +44,15 @@
/**
* @hide
*/
- @IntDef(prefix = { "POLLING_LOOP_TYPE_"}, value = { POLLING_LOOP_TYPE_A, POLLING_LOOP_TYPE_B,
- POLLING_LOOP_TYPE_F, POLLING_LOOP_TYPE_OFF, POLLING_LOOP_TYPE_ON })
+ @IntDef(prefix = { "POLLING_LOOP_TYPE_"},
+ value = {
+ POLLING_LOOP_TYPE_A,
+ POLLING_LOOP_TYPE_B,
+ POLLING_LOOP_TYPE_F,
+ POLLING_LOOP_TYPE_OFF,
+ POLLING_LOOP_TYPE_ON,
+ POLLING_LOOP_TYPE_UNKNOWN
+ })
@Retention(RetentionPolicy.SOURCE)
@FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
public @interface PollingFrameType {}
diff --git a/packages/CarrierDefaultApp/res/values-ca/strings.xml b/packages/CarrierDefaultApp/res/values-ca/strings.xml
index ec032d5..6e6a862 100644
--- a/packages/CarrierDefaultApp/res/values-ca/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ca/strings.xml
@@ -16,7 +16,7 @@
<string name="ssl_error_continue" msgid="1138548463994095584">"Continua igualment mitjançant el navegador"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Optimització de rendiment"</string>
<string name="performance_boost_notification_title" msgid="3126203390685781861">"Opcions 5G del teu operador"</string>
- <string name="performance_boost_notification_detail" msgid="216569851036236346">"Visita el lloc web de %s per veure les opcions relacionades amb la teva experiència a l\'aplicació"</string>
+ <string name="performance_boost_notification_detail" msgid="216569851036236346">"Visita el lloc web de %s per veure les opcions relacionades amb la teva experiència de l\'aplicació"</string>
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ara no"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Gestiona"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Compra una optimització de rendiment."</string>
diff --git a/packages/CarrierDefaultApp/res/values-fa/strings.xml b/packages/CarrierDefaultApp/res/values-fa/strings.xml
index abf47fb..d9afe873 100644
--- a/packages/CarrierDefaultApp/res/values-fa/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-fa/strings.xml
@@ -17,7 +17,7 @@
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"تقویتکننده عملکرد"</string>
<string name="performance_boost_notification_title" msgid="3126203390685781861">"گزینههای نسل پنجم شرکت مخابراتی شما"</string>
<string name="performance_boost_notification_detail" msgid="216569851036236346">"برای دیدن گزینههای مرتبط با تجربه برنامه، به وبسایت %s مراجعه کنید"</string>
- <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"اکنون نه"</string>
+ <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"حالا نه"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"مدیریت"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"تقویتکننده عملکرد خریداری کنید."</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ky/strings.xml b/packages/CompanionDeviceManager/res/values-ky/strings.xml
index 1b72477..23a2e7f 100644
--- a/packages/CompanionDeviceManager/res/values-ky/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ky/strings.xml
@@ -59,7 +59,7 @@
<string name="permission_microphone" msgid="2152206421428732949">"Микрофон"</string>
<string name="permission_call_logs" msgid="5546761417694586041">"Чалуулар тизмеси"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Жакын жердеги түзмөктөр"</string>
- <string name="permission_media_routing_control" msgid="5498639511586715253">"Медиа чыгарылышын өзгөртүү"</string>
+ <string name="permission_media_routing_control" msgid="5498639511586715253">"Медианы чыгаруучу булакты өзгөртүү"</string>
<string name="permission_storage" msgid="6831099350839392343">"Сүрөттөр жана медиафайлдар"</string>
<string name="permission_notifications" msgid="4099418516590632909">"Билдирмелер"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Колдонмолор"</string>
diff --git a/packages/CompanionDeviceManager/res/values-mk/strings.xml b/packages/CompanionDeviceManager/res/values-mk/strings.xml
index 2d7c2d3..6a162c0 100644
--- a/packages/CompanionDeviceManager/res/values-mk/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-mk/strings.xml
@@ -59,7 +59,7 @@
<string name="permission_microphone" msgid="2152206421428732949">"Микрофон"</string>
<string name="permission_call_logs" msgid="5546761417694586041">"Евиденција на повици"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Уреди во близина"</string>
- <string name="permission_media_routing_control" msgid="5498639511586715253">"Промена на излезот за аудио"</string>
+ <string name="permission_media_routing_control" msgid="5498639511586715253">"Менување излез за аудио/видео"</string>
<string name="permission_storage" msgid="6831099350839392343">"Аудиовизуелни содржини"</string>
<string name="permission_notifications" msgid="4099418516590632909">"Известувања"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Апликации"</string>
diff --git a/packages/CompanionDeviceManager/res/values-tr/strings.xml b/packages/CompanionDeviceManager/res/values-tr/strings.xml
index 5852657..815d256a 100644
--- a/packages/CompanionDeviceManager/res/values-tr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-tr/strings.xml
@@ -59,7 +59,7 @@
<string name="permission_microphone" msgid="2152206421428732949">"Mikrofon"</string>
<string name="permission_call_logs" msgid="5546761417694586041">"Arama kayıtları"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Yakındaki cihazlar"</string>
- <string name="permission_media_routing_control" msgid="5498639511586715253">"Medya çıkışını değiştirin"</string>
+ <string name="permission_media_routing_control" msgid="5498639511586715253">"Medya çıkışını değiştir"</string>
<string name="permission_storage" msgid="6831099350839392343">"Fotoğraflar ve medya"</string>
<string name="permission_notifications" msgid="4099418516590632909">"Bildirimler"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Uygulamalar"</string>
diff --git a/packages/CredentialManager/res/layout/credman_dropdown_presentation_layout.xml b/packages/CredentialManager/res/layout/credman_dropdown_presentation_layout.xml
index 2aff2c3..3fc6154 100644
--- a/packages/CredentialManager/res/layout/credman_dropdown_presentation_layout.xml
+++ b/packages/CredentialManager/res/layout/credman_dropdown_presentation_layout.xml
@@ -46,6 +46,7 @@
android:paddingEnd="@dimen/autofill_view_right_padding"
android:paddingTop="@dimen/autofill_view_top_padding"
android:paddingBottom="@dimen/autofill_view_bottom_padding"
+ android:textDirection="locale"
android:orientation="vertical">
<TextView
@@ -53,6 +54,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?androidprv:attr/materialColorOnSurface"
+ android:textDirection="locale"
style="@style/autofill.TextTitle"/>
<TextView
@@ -60,6 +62,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?androidprv:attr/materialColorOnSurfaceVariant"
+ android:textDirection="locale"
style="@style/autofill.TextSubtitle"/>
</LinearLayout>
diff --git a/packages/CredentialManager/res/values-fr/strings.xml b/packages/CredentialManager/res/values-fr/strings.xml
index b239fc3..8617c6a 100644
--- a/packages/CredentialManager/res/values-fr/strings.xml
+++ b/packages/CredentialManager/res/values-fr/strings.xml
@@ -20,7 +20,7 @@
<string name="app_name" msgid="4539824758261855508">"Gestionnaire d\'identifiants"</string>
<string name="string_cancel" msgid="6369133483981306063">"Annuler"</string>
<string name="string_continue" msgid="1346732695941131882">"Continuer"</string>
- <string name="string_more_options" msgid="2763852250269945472">"Autre façon"</string>
+ <string name="string_more_options" msgid="2763852250269945472">"Autre option"</string>
<string name="string_learn_more" msgid="4541600451688392447">"En savoir plus"</string>
<string name="content_description_show_password" msgid="3283502010388521607">"Afficher le mot de passe"</string>
<string name="content_description_hide_password" msgid="6841375971631767996">"Masquer le mot de passe"</string>
@@ -40,7 +40,7 @@
<string name="choose_provider_title" msgid="8870795677024868108">"Choisissez où enregistrer vos <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
<string name="choose_provider_body" msgid="4967074531845147434">"Sélectionnez un gestionnaire de mots de passe pour enregistrer vos informations et vous connecter plus rapidement la prochaine fois"</string>
<string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Créer une clé d\'accès pour se connecter à <xliff:g id="APP_NAME">%1$s</xliff:g> ?"</string>
- <string name="choose_create_option_password_title" msgid="4481366993598649224">"Enregistrer un mot de passe pour se connecter à <xliff:g id="APP_NAME">%1$s</xliff:g> ?"</string>
+ <string name="choose_create_option_password_title" msgid="4481366993598649224">"Enregistrer le mot de passe pour se connecter à <xliff:g id="APP_NAME">%1$s</xliff:g> ?"</string>
<string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Enregistrer les informations de connexion pour <xliff:g id="APP_NAME">%1$s</xliff:g> ?"</string>
<string name="passkey" msgid="632353688396759522">"clé d\'accès"</string>
<string name="password" msgid="6738570945182936667">"mot de passe"</string>
diff --git a/packages/CredentialManager/res/values-hy/strings.xml b/packages/CredentialManager/res/values-hy/strings.xml
index 868357f..3ec7da3 100644
--- a/packages/CredentialManager/res/values-hy/strings.xml
+++ b/packages/CredentialManager/res/values-hy/strings.xml
@@ -28,7 +28,7 @@
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Անցաբառերի շնորհիվ դուք բարդ գաղտնաբառեր ստեղծելու կամ հիշելու անհրաժեշտություն չեք ունենա"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Անցաբառերը գաղտնագրված թվային բանալիներ են, որոնք ստեղծվում են մատնահետքի, դեմքով ապակողպման կամ էկրանի կողպման օգտագործմամբ"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Դուք կարող եք մուտք գործել այլ սարքերում, քանի որ մուտքի բանալիները պահվում են գաղտնաբառերի կառավարիչում"</string>
- <string name="more_about_passkeys_title" msgid="7797903098728837795">"Ավելին՝ անցաբառերի մասին"</string>
+ <string name="more_about_passkeys_title" msgid="7797903098728837795">"Ավելին՝ մուտքի բանալիների մասին"</string>
<string name="passwordless_technology_title" msgid="2497513482056606668">"Գաղտնաբառեր չպահանջող տեխնոլոգիա"</string>
<string name="passwordless_technology_detail" msgid="6853928846532955882">"Մուտքի բանալիները ձեզ թույլ են տալիս մուտք գործել առանց գաղտնաբառերի։ Ձեզ պարզապես հարկավոր է օգտագործել ձեր մատնահետքը, դիմաճանաչումը, PIN կոդը կամ նախշը՝ ձեր ինքնությունը հաստատելու և մուտքի բանալի ստեղծելու համար։"</string>
<string name="public_key_cryptography_title" msgid="6751970819265298039">"Բաց բանալու կրիպտոգրաֆիա"</string>
@@ -36,7 +36,7 @@
<string name="improved_account_security_title" msgid="1069841917893513424">"Հաշվի բարելավված անվտանգություն"</string>
<string name="improved_account_security_detail" msgid="9123750251551844860">"Յուրաքանչյուր բանալի բացառապես կապված է հավելվածի կամ կայքի հետ, որի համար այն ստեղծվել է, ուստի դուք երբեք չեք կարող սխալմամբ մուտք գործել կեղծ հավելված կամ կայք։ Բացի այդ՝ սերվերներում պահվում են միայն բաց բանալիներ, ինչը զգալիորեն դժվարացնում է կոտրումը։"</string>
<string name="seamless_transition_title" msgid="5335622196351371961">"Սահուն անցում"</string>
- <string name="seamless_transition_detail" msgid="4475509237171739843">"Թեև մենք առանց գաղտնաբառերի ապագայի ճանապարհին ենք, դրանք դեռ հասանելի կլինեն անցաբառերի հետ մեկտեղ։"</string>
+ <string name="seamless_transition_detail" msgid="4475509237171739843">"Թեև մենք առանց գաղտնաբառերի ապագայի ճանապարհին ենք, դրանք դեռ հասանելի կլինեն մուտքի բանալիների հետ մեկտեղ։"</string>
<string name="choose_provider_title" msgid="8870795677024868108">"Նշեք, թե որտեղ եք ուզում պահել ձեր <xliff:g id="CREATETYPES">%1$s</xliff:g>ը"</string>
<string name="choose_provider_body" msgid="4967074531845147434">"Ընտրեք գաղտնաբառերի կառավարիչ՝ ձեր տեղեկությունները պահելու և հաջորդ անգամ ավելի արագ մուտք գործելու համար"</string>
<string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Ստեղծե՞լ մուտքի բանալի՝ <xliff:g id="APP_NAME">%1$s</xliff:g> հավելված մուտք գործելու համար"</string>
@@ -44,7 +44,7 @@
<string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Պահե՞լ «<xliff:g id="APP_NAME">%1$s</xliff:g>» հավելվածի մուտքի տվյալները"</string>
<string name="passkey" msgid="632353688396759522">"մուտքի բանալի"</string>
<string name="password" msgid="6738570945182936667">"գաղտնաբառ"</string>
- <string name="passkeys" msgid="5733880786866559847">"անցաբառեր"</string>
+ <string name="passkeys" msgid="5733880786866559847">"մուտքի բանալիներ"</string>
<string name="passwords" msgid="5419394230391253816">"գաղտնաբառեր"</string>
<string name="sign_ins" msgid="4710739369149469208">"մուտք"</string>
<string name="sign_in_info" msgid="2627704710674232328">"մուտքի տվյալներ"</string>
diff --git a/packages/CredentialManager/res/values-sk/strings.xml b/packages/CredentialManager/res/values-sk/strings.xml
index 8e6b32c..5b0be91 100644
--- a/packages/CredentialManager/res/values-sk/strings.xml
+++ b/packages/CredentialManager/res/values-sk/strings.xml
@@ -48,7 +48,7 @@
<string name="passwords" msgid="5419394230391253816">"heslá"</string>
<string name="sign_ins" msgid="4710739369149469208">"prihlasovacie údaje"</string>
<string name="sign_in_info" msgid="2627704710674232328">"prihlasovacie údaje"</string>
- <string name="save_credential_to_title" msgid="3172811692275634301">"Uložiť <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> do"</string>
+ <string name="save_credential_to_title" msgid="3172811692275634301">"Kam uložiť <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g>?"</string>
<string name="create_passkey_in_other_device_title" msgid="2360053098931886245">"Chcete vytvoriť prístupový kľúč v inom zariadení?"</string>
<string name="save_password_on_other_device_title" msgid="5829084591948321207">"Chcete uložiť heslo v inom zariadení?"</string>
<string name="save_sign_in_on_other_device_title" msgid="2827990118560134692">"Chcete uložiť prihlasovacie údaje v inom zariadení?"</string>
diff --git a/packages/CredentialManager/res/values-uk/strings.xml b/packages/CredentialManager/res/values-uk/strings.xml
index cd5b7bb..e746130 100644
--- a/packages/CredentialManager/res/values-uk/strings.xml
+++ b/packages/CredentialManager/res/values-uk/strings.xml
@@ -48,7 +48,7 @@
<string name="passwords" msgid="5419394230391253816">"паролі"</string>
<string name="sign_ins" msgid="4710739369149469208">"дані для входу"</string>
<string name="sign_in_info" msgid="2627704710674232328">"дані для входу"</string>
- <string name="save_credential_to_title" msgid="3172811692275634301">"Зберегти <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> в"</string>
+ <string name="save_credential_to_title" msgid="3172811692275634301">"Де слід зберегти <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g>?"</string>
<string name="create_passkey_in_other_device_title" msgid="2360053098931886245">"Створити ключ доступу на іншому пристрої?"</string>
<string name="save_password_on_other_device_title" msgid="5829084591948321207">"Зберегти пароль на іншому пристрої?"</string>
<string name="save_sign_in_on_other_device_title" msgid="2827990118560134692">"Зберегти дані для входу на іншому пристрої?"</string>
diff --git a/packages/CredentialManager/res/values/strings.xml b/packages/CredentialManager/res/values/strings.xml
index 46a5138..0bae63a 100644
--- a/packages/CredentialManager/res/values/strings.xml
+++ b/packages/CredentialManager/res/values/strings.xml
@@ -24,7 +24,7 @@
<string name="string_cancel">Cancel</string>
<!-- This is a label for a button that takes user to the next screen. [CHAR LIMIT=20] -->
<string name="string_continue">Continue</string>
- <!-- This is a label for a button that leads to a holistic view of all different options where the user can save their new app credential. [CHAR LIMIT=20] -->
+ <!-- This is a label for a button that leads to a holistic view of all different options where the user can save their new app credential. [CHAR LIMIT=30] -->
<string name="string_more_options">Save another way</string>
<!-- This is a label for a button that links to additional information about passkeys. [CHAR LIMIT=20] -->
<string name="string_learn_more">Learn more</string>
@@ -174,4 +174,4 @@
<!-- Text shown in the dropdown presentation to select more sign in options. [CHAR LIMIT=120] -->
<string name="dropdown_presentation_more_sign_in_options_text">Sign-in options</string>
<string name="more_options_content_description">More</string>
-</resources>
\ No newline at end of file
+</resources>
diff --git a/packages/CredentialManager/res/xml/autofill_service_configuration.xml b/packages/CredentialManager/res/xml/autofill_service_configuration.xml
index 25cc094..0151add 100644
--- a/packages/CredentialManager/res/xml/autofill_service_configuration.xml
+++ b/packages/CredentialManager/res/xml/autofill_service_configuration.xml
@@ -5,6 +5,6 @@
Note: This file is ignored for devices older that API 31
See https://developer.android.com/about/versions/12/backup-restore
-->
-<autofill-service-configuration
+<autofill-service
xmlns:android="http://schemas.android.com/apk/res/android"
android:supportsInlineSuggestions="true"/>
\ No newline at end of file
diff --git a/packages/InputDevices/res/values-af/strings.xml b/packages/InputDevices/res/values-af/strings.xml
index 232df24..9369140 100644
--- a/packages/InputDevices/res/values-af/strings.xml
+++ b/packages/InputDevices/res/values-af/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongools"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgies"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thai (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"Thais (Pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-am/strings.xml b/packages/InputDevices/res/values-am/strings.xml
index 9a8bd37..16f6437 100644
--- a/packages/InputDevices/res/values-am/strings.xml
+++ b/packages/InputDevices/res/values-am/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"ሞንጎሊያኛ"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"ጂዮርጂያኛ"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"ታይላንድኛ (ኬድማኒ)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"ታይላንድኛ (ፓታሾት)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-ar/strings.xml b/packages/InputDevices/res/values-ar/strings.xml
index e79519a..93223ba 100644
--- a/packages/InputDevices/res/values-ar/strings.xml
+++ b/packages/InputDevices/res/values-ar/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"المنغولية"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"الجورجية"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"التايلاندية (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"التايلاندية (Pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-as/strings.xml b/packages/InputDevices/res/values-as/strings.xml
index 802b13e..c57b591 100644
--- a/packages/InputDevices/res/values-as/strings.xml
+++ b/packages/InputDevices/res/values-as/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolian"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgian"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"থাই (কেডমানি)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"থাই (পাটাচ’টে)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-az/strings.xml b/packages/InputDevices/res/values-az/strings.xml
index 4a8e7ff..9c6bdb3 100644
--- a/packages/InputDevices/res/values-az/strings.xml
+++ b/packages/InputDevices/res/values-az/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Monqol"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Gürcü"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Tay (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"Tay (Pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-b+sr+Latn/strings.xml b/packages/InputDevices/res/values-b+sr+Latn/strings.xml
index 9126a74..80ecff5 100644
--- a/packages/InputDevices/res/values-b+sr+Latn/strings.xml
+++ b/packages/InputDevices/res/values-b+sr+Latn/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"mongolska"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"gruzijska"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"tajski (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"tajski (Pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-be/strings.xml b/packages/InputDevices/res/values-be/strings.xml
index 4dd59bf..c5aa66f 100644
--- a/packages/InputDevices/res/values-be/strings.xml
+++ b/packages/InputDevices/res/values-be/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Мангольская"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Грузінская"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Тайская (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"Тайская (Патачотэ)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-bg/strings.xml b/packages/InputDevices/res/values-bg/strings.xml
index 3dbd6f7..1260d6a 100644
--- a/packages/InputDevices/res/values-bg/strings.xml
+++ b/packages/InputDevices/res/values-bg/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"монголски"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"грузински"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"тайландски (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"тайландски (Pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-bn/strings.xml b/packages/InputDevices/res/values-bn/strings.xml
index 0d8e5d8..a038da9 100644
--- a/packages/InputDevices/res/values-bn/strings.xml
+++ b/packages/InputDevices/res/values-bn/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"মঙ্গোলিয়ান"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"জর্জিয়ান"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"থাই (কেডমানি)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"থাই (পাট্টাচোটে)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-bs/strings.xml b/packages/InputDevices/res/values-bs/strings.xml
index bb12f00..12e93bc 100644
--- a/packages/InputDevices/res/values-bs/strings.xml
+++ b/packages/InputDevices/res/values-bs/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"mongolski"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"gruzijski"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"tajlandski (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"tajlandski (pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-ca/strings.xml b/packages/InputDevices/res/values-ca/strings.xml
index 86b6421..8a1e059 100644
--- a/packages/InputDevices/res/values-ca/strings.xml
+++ b/packages/InputDevices/res/values-ca/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongol"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgià"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Tai (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"Tai (Pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-cs/strings.xml b/packages/InputDevices/res/values-cs/strings.xml
index 7832e6e..9ee17e1 100644
--- a/packages/InputDevices/res/values-cs/strings.xml
+++ b/packages/InputDevices/res/values-cs/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"mongolština"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"gruzínština"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"thajština (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"thajština (Pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-da/strings.xml b/packages/InputDevices/res/values-da/strings.xml
index 51cb1ae..db75d3e 100644
--- a/packages/InputDevices/res/values-da/strings.xml
+++ b/packages/InputDevices/res/values-da/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolsk"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgisk"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thai (kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"Thai (pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-de/strings.xml b/packages/InputDevices/res/values-de/strings.xml
index c4de5a8..3db695e 100644
--- a/packages/InputDevices/res/values-de/strings.xml
+++ b/packages/InputDevices/res/values-de/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolisch"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgisch"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thailändisch (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"Thailändisch (Pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-el/strings.xml b/packages/InputDevices/res/values-el/strings.xml
index 48f7c025..cb7aa2c 100644
--- a/packages/InputDevices/res/values-el/strings.xml
+++ b/packages/InputDevices/res/values-el/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Μογγολικά"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Γεωργιανά"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Ταϊλανδικά (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"Ταϊλανδικά (Pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-en-rAU/strings.xml b/packages/InputDevices/res/values-en-rAU/strings.xml
index 2d37370..d113201 100644
--- a/packages/InputDevices/res/values-en-rAU/strings.xml
+++ b/packages/InputDevices/res/values-en-rAU/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolian"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgian"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thai (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"Thai (Pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-en-rCA/strings.xml b/packages/InputDevices/res/values-en-rCA/strings.xml
index f863fe9..cae7f00 100644
--- a/packages/InputDevices/res/values-en-rCA/strings.xml
+++ b/packages/InputDevices/res/values-en-rCA/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolian"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgian"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thai (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"Thai (Pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-en-rGB/strings.xml b/packages/InputDevices/res/values-en-rGB/strings.xml
index 2d37370..d113201 100644
--- a/packages/InputDevices/res/values-en-rGB/strings.xml
+++ b/packages/InputDevices/res/values-en-rGB/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolian"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgian"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thai (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"Thai (Pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-en-rIN/strings.xml b/packages/InputDevices/res/values-en-rIN/strings.xml
index 2d37370..d113201 100644
--- a/packages/InputDevices/res/values-en-rIN/strings.xml
+++ b/packages/InputDevices/res/values-en-rIN/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolian"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgian"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thai (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"Thai (Pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-en-rXC/strings.xml b/packages/InputDevices/res/values-en-rXC/strings.xml
index 0a4344b..71c84da 100644
--- a/packages/InputDevices/res/values-en-rXC/strings.xml
+++ b/packages/InputDevices/res/values-en-rXC/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolian"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgian"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thai (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"Thai (Pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-es-rUS/strings.xml b/packages/InputDevices/res/values-es-rUS/strings.xml
index 216e91f..7490f7d 100644
--- a/packages/InputDevices/res/values-es-rUS/strings.xml
+++ b/packages/InputDevices/res/values-es-rUS/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongol"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgiano"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Tailandés (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"Tailandés (Pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-es/strings.xml b/packages/InputDevices/res/values-es/strings.xml
index 648b3d2..22b8cda 100644
--- a/packages/InputDevices/res/values-es/strings.xml
+++ b/packages/InputDevices/res/values-es/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongol"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgiano"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Tailandés (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"Tailandés (Pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-et/strings.xml b/packages/InputDevices/res/values-et/strings.xml
index 0aba840..34fd3d7 100644
--- a/packages/InputDevices/res/values-et/strings.xml
+++ b/packages/InputDevices/res/values-et/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"mongoli"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"gruusia"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"tai (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"Tai (Pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-eu/strings.xml b/packages/InputDevices/res/values-eu/strings.xml
index c1a0dac..15535fd 100644
--- a/packages/InputDevices/res/values-eu/strings.xml
+++ b/packages/InputDevices/res/values-eu/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongoliarra"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgiarra"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thailandiarra (kedmanee-a)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"Thailandiarra (pattachote-a)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-fa/strings.xml b/packages/InputDevices/res/values-fa/strings.xml
index 4fba26d..11280dd 100644
--- a/packages/InputDevices/res/values-fa/strings.xml
+++ b/packages/InputDevices/res/values-fa/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"مغولی"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"گرجستانی"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"تایلندی (کدمانی)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"تایلندی (پاتاچوته)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-fi/strings.xml b/packages/InputDevices/res/values-fi/strings.xml
index b8199a8..6c6d4cf 100644
--- a/packages/InputDevices/res/values-fi/strings.xml
+++ b/packages/InputDevices/res/values-fi/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"mongoli"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"georgia"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"thai (kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"thai (pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-fr-rCA/strings.xml b/packages/InputDevices/res/values-fr-rCA/strings.xml
index f375dad..5c931cf 100644
--- a/packages/InputDevices/res/values-fr-rCA/strings.xml
+++ b/packages/InputDevices/res/values-fr-rCA/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongol"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Géorgien"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thaï (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"Thaï (Pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-fr/strings.xml b/packages/InputDevices/res/values-fr/strings.xml
index e19d9dc4..1323675 100644
--- a/packages/InputDevices/res/values-fr/strings.xml
+++ b/packages/InputDevices/res/values-fr/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongol"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Géorgien"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thaï (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"Thaï (Pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-gl/strings.xml b/packages/InputDevices/res/values-gl/strings.xml
index c878e1e..cedff5b 100644
--- a/packages/InputDevices/res/values-gl/strings.xml
+++ b/packages/InputDevices/res/values-gl/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongol"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Xeorxiano"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Tailandés (kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"Tailandés (pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-gu/strings.xml b/packages/InputDevices/res/values-gu/strings.xml
index d5fe48c..cbd4c40 100644
--- a/packages/InputDevices/res/values-gu/strings.xml
+++ b/packages/InputDevices/res/values-gu/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"મોંગોલિયન"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"જ્યોર્જિઅન"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"થાઇ (કેડમાની)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"થાઇ (પટ્ટાશોટે)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-hi/strings.xml b/packages/InputDevices/res/values-hi/strings.xml
index 3fa45b1..7e3df82 100644
--- a/packages/InputDevices/res/values-hi/strings.xml
+++ b/packages/InputDevices/res/values-hi/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"मंगोलियन"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"जॉर्जियन कीबोर्ड का लेआउट"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"थाई (केडमेनी)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"थाई (पटैचोटे)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-hr/strings.xml b/packages/InputDevices/res/values-hr/strings.xml
index 409a321..ba3dc51 100644
--- a/packages/InputDevices/res/values-hr/strings.xml
+++ b/packages/InputDevices/res/values-hr/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolski"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Gruzijska"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"tajlandski (kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"Tajski (pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-hu/strings.xml b/packages/InputDevices/res/values-hu/strings.xml
index 3131bc5..c42e009 100644
--- a/packages/InputDevices/res/values-hu/strings.xml
+++ b/packages/InputDevices/res/values-hu/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"mongol"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"grúz"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"thai (kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"thai (pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-hy/strings.xml b/packages/InputDevices/res/values-hy/strings.xml
index 2307a9b..d85cf9d 100644
--- a/packages/InputDevices/res/values-hy/strings.xml
+++ b/packages/InputDevices/res/values-hy/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Մոնղոլերեն"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"վրացերեն"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"թայերեն (քեդմանի)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"թայերեն (պատաչոտ)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-in/strings.xml b/packages/InputDevices/res/values-in/strings.xml
index 69ba58a..d504540 100644
--- a/packages/InputDevices/res/values-in/strings.xml
+++ b/packages/InputDevices/res/values-in/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolia"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgia"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thai (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"Thai (Pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-is/strings.xml b/packages/InputDevices/res/values-is/strings.xml
index 5107503..637874c 100644
--- a/packages/InputDevices/res/values-is/strings.xml
+++ b/packages/InputDevices/res/values-is/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"mongólska"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"georgíska"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Taílenskt (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"Taílenskt (Pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-it/strings.xml b/packages/InputDevices/res/values-it/strings.xml
index 740cf37..eed8316 100644
--- a/packages/InputDevices/res/values-it/strings.xml
+++ b/packages/InputDevices/res/values-it/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolo"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgiano"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thai (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"Thai (Pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-iw/strings.xml b/packages/InputDevices/res/values-iw/strings.xml
index 6badc3f..8cfe2cb 100644
--- a/packages/InputDevices/res/values-iw/strings.xml
+++ b/packages/InputDevices/res/values-iw/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"מונגולית"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"גיאורגית"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"תאית (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"תאית (Pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-ja/strings.xml b/packages/InputDevices/res/values-ja/strings.xml
index 9676886..d1b334b 100644
--- a/packages/InputDevices/res/values-ja/strings.xml
+++ b/packages/InputDevices/res/values-ja/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"モンゴル語"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"ジョージア語"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"タイ語(Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"タイ語(Pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-ka/strings.xml b/packages/InputDevices/res/values-ka/strings.xml
index 93735c9..8928f68 100644
--- a/packages/InputDevices/res/values-ka/strings.xml
+++ b/packages/InputDevices/res/values-ka/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"მონღოლური"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"ქართული"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"ტაილანდური (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"ტაილანდური (Pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-kk/strings.xml b/packages/InputDevices/res/values-kk/strings.xml
index 603b6c7..cf3d3ca 100644
--- a/packages/InputDevices/res/values-kk/strings.xml
+++ b/packages/InputDevices/res/values-kk/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Моңғол"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Грузин"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Тай (кедмани)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"Тай (паттачот)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-km/strings.xml b/packages/InputDevices/res/values-km/strings.xml
index 0f3832e..53eb6f5 100644
--- a/packages/InputDevices/res/values-km/strings.xml
+++ b/packages/InputDevices/res/values-km/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"មុងហ្គោលី"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"ហ្សកហ្ស៊ី"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"ថៃ (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"ថៃ (ប៉ាតាឈោត)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-kn/strings.xml b/packages/InputDevices/res/values-kn/strings.xml
index 96b9294..c743a6e 100644
--- a/packages/InputDevices/res/values-kn/strings.xml
+++ b/packages/InputDevices/res/values-kn/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"ಮಂಗೋಲಿಯನ್"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"ಜಾರ್ಜಿಯನ್"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"ಥಾಯ್ (ಕೆಡ್ಮನೀ)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"ಥಾಯ್ (ಪಟ್ಟಚೋಟ್)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-ko/strings.xml b/packages/InputDevices/res/values-ko/strings.xml
index 9956f26..0e375dd 100644
--- a/packages/InputDevices/res/values-ko/strings.xml
+++ b/packages/InputDevices/res/values-ko/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"몽골어"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"조지아어"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"태국어(Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"태국어(Pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-ky/strings.xml b/packages/InputDevices/res/values-ky/strings.xml
index 0b1ab5a..dad5c91 100644
--- a/packages/InputDevices/res/values-ky/strings.xml
+++ b/packages/InputDevices/res/values-ky/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Монголчо"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Грузинче"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Тайча (Kedmanee баскычтобу)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"Тайча (Pattachote баскычтобу)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-lo/strings.xml b/packages/InputDevices/res/values-lo/strings.xml
index 3effea7..0794bde 100644
--- a/packages/InputDevices/res/values-lo/strings.xml
+++ b/packages/InputDevices/res/values-lo/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"ມອງໂກລຽນ"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"ຈໍຈຽນ"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"ໄທ (ເກດມະນີ)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"ໄທ (ປັດຕະໂຊຕິ)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-lt/strings.xml b/packages/InputDevices/res/values-lt/strings.xml
index 82cf221..0cceec7 100644
--- a/packages/InputDevices/res/values-lt/strings.xml
+++ b/packages/InputDevices/res/values-lt/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolų"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Gruzinų"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Tajų („Kedmanee“)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"Tajų („Pattachote“)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-lv/strings.xml b/packages/InputDevices/res/values-lv/strings.xml
index 952f803..9b52854 100644
--- a/packages/InputDevices/res/values-lv/strings.xml
+++ b/packages/InputDevices/res/values-lv/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongoļu"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Gruzīnu"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Taju valoda (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"Taju (Pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-mk/strings.xml b/packages/InputDevices/res/values-mk/strings.xml
index 2709689..4e8be46 100644
--- a/packages/InputDevices/res/values-mk/strings.xml
+++ b/packages/InputDevices/res/values-mk/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"монголски"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"грузиски"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"тајландски (кедмани)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"тајландски (Pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-ml/strings.xml b/packages/InputDevices/res/values-ml/strings.xml
index 8559a21..4b2a5fd 100644
--- a/packages/InputDevices/res/values-ml/strings.xml
+++ b/packages/InputDevices/res/values-ml/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"മംഗോളിയൻ"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"ജോര്ജ്ജിയൻ"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"തായ് (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"തായ് (Pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-mn/strings.xml b/packages/InputDevices/res/values-mn/strings.xml
index 397c947..a7a1799 100644
--- a/packages/InputDevices/res/values-mn/strings.xml
+++ b/packages/InputDevices/res/values-mn/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Монгол"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Гүрж"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Тай (кедмани)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"Тай (паттачоте)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-mr/strings.xml b/packages/InputDevices/res/values-mr/strings.xml
index a818afe..5e4baa0 100644
--- a/packages/InputDevices/res/values-mr/strings.xml
+++ b/packages/InputDevices/res/values-mr/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"मंगोलियन"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"जॉर्जियन"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"थाई (केडमानी)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"थाई (पट्टाचोटे)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-ms/strings.xml b/packages/InputDevices/res/values-ms/strings.xml
index 94ec21a..9e4c190 100644
--- a/packages/InputDevices/res/values-ms/strings.xml
+++ b/packages/InputDevices/res/values-ms/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Bahasa Mongolia"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Bahasa Georgia"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thai (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"Thai (Pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-my/strings.xml b/packages/InputDevices/res/values-my/strings.xml
index babd1ea..5dbdc70 100644
--- a/packages/InputDevices/res/values-my/strings.xml
+++ b/packages/InputDevices/res/values-my/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"မွန်ဂိုလီးယား"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"ဂျော်ဂျီယာ"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"ထိုင်း (ကတ်မနီး)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"ထိုင်း (ပတ်တာချုတ်)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-nb/strings.xml b/packages/InputDevices/res/values-nb/strings.xml
index 5c465da..1e9af39 100644
--- a/packages/InputDevices/res/values-nb/strings.xml
+++ b/packages/InputDevices/res/values-nb/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolsk"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgisk"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thai (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"Thai (Pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-ne/strings.xml b/packages/InputDevices/res/values-ne/strings.xml
index c32e458..ab22576 100644
--- a/packages/InputDevices/res/values-ne/strings.xml
+++ b/packages/InputDevices/res/values-ne/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"मङ्गोलियाली"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"जर्जियाली"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"थाई (केडमानी)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"थाई (पत्ताचोते)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-nl/strings.xml b/packages/InputDevices/res/values-nl/strings.xml
index 1d399ae..d28ee9b 100644
--- a/packages/InputDevices/res/values-nl/strings.xml
+++ b/packages/InputDevices/res/values-nl/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongools"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgisch"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thai (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"Thai (Pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-or/strings.xml b/packages/InputDevices/res/values-or/strings.xml
index 0d0fbaf..e92c155 100644
--- a/packages/InputDevices/res/values-or/strings.xml
+++ b/packages/InputDevices/res/values-or/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"ମଙ୍ଗୋଲିଆନ୍"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"ଜର୍ଜିଆନ୍"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"ଥାଇ (କେଡମାନି)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"ଥାଇ (ପାଟ୍ଟାଚୋଟେ)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-pa/strings.xml b/packages/InputDevices/res/values-pa/strings.xml
index fbf50ae..f766297 100644
--- a/packages/InputDevices/res/values-pa/strings.xml
+++ b/packages/InputDevices/res/values-pa/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"ਮੰਗੋਲੀਆਈ"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"ਜਾਰਜੀਆਈ"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"ਥਾਈ (ਕੇਦਮਨੀ)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"ਥਾਈ (ਪੈਟਾਸ਼ੋਟੇ)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-pl/strings.xml b/packages/InputDevices/res/values-pl/strings.xml
index 6bf6f48..e202463 100644
--- a/packages/InputDevices/res/values-pl/strings.xml
+++ b/packages/InputDevices/res/values-pl/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"mongolski"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"gruziński"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"tajski (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"tajski (Pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-pt-rBR/strings.xml b/packages/InputDevices/res/values-pt-rBR/strings.xml
index e2bad4f..4a0c3be 100644
--- a/packages/InputDevices/res/values-pt-rBR/strings.xml
+++ b/packages/InputDevices/res/values-pt-rBR/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongol"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgiano"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Tailandês (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"Tailandês (pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-pt-rPT/strings.xml b/packages/InputDevices/res/values-pt-rPT/strings.xml
index 7ade82f..c54b620 100644
--- a/packages/InputDevices/res/values-pt-rPT/strings.xml
+++ b/packages/InputDevices/res/values-pt-rPT/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongol"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgiano"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Tailandês (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"Tailandês (Pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-pt/strings.xml b/packages/InputDevices/res/values-pt/strings.xml
index e2bad4f..4a0c3be 100644
--- a/packages/InputDevices/res/values-pt/strings.xml
+++ b/packages/InputDevices/res/values-pt/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongol"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgiano"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Tailandês (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"Tailandês (pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-ro/strings.xml b/packages/InputDevices/res/values-ro/strings.xml
index 248b3ad..d91635b 100644
--- a/packages/InputDevices/res/values-ro/strings.xml
+++ b/packages/InputDevices/res/values-ro/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolă"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgiană"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thailandeză (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"Thailandeză (Pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-ru/strings.xml b/packages/InputDevices/res/values-ru/strings.xml
index 171b713..da1a83a 100644
--- a/packages/InputDevices/res/values-ru/strings.xml
+++ b/packages/InputDevices/res/values-ru/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"монгольский"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"грузинский"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Тайский (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"Тайский (Pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-si/strings.xml b/packages/InputDevices/res/values-si/strings.xml
index 27b031b..97aed62 100644
--- a/packages/InputDevices/res/values-si/strings.xml
+++ b/packages/InputDevices/res/values-si/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"මොන්ගෝලියානු"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"ජෝර්ජියානු"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"තායි (කෙඩ්මනී)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"තායි (පට්ටචෝටේ)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-sk/strings.xml b/packages/InputDevices/res/values-sk/strings.xml
index 7d4315b..6f387ad 100644
--- a/packages/InputDevices/res/values-sk/strings.xml
+++ b/packages/InputDevices/res/values-sk/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"mongolské"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"gruzínske"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"thajčina (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"thajčina (Pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-sl/strings.xml b/packages/InputDevices/res/values-sl/strings.xml
index fc8f146..32ca0ad 100644
--- a/packages/InputDevices/res/values-sl/strings.xml
+++ b/packages/InputDevices/res/values-sl/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"mongolščina"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"gruzinščina"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"tajščina (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"tajščina (Pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-sq/strings.xml b/packages/InputDevices/res/values-sq/strings.xml
index 65cec14..c33ba4a 100644
--- a/packages/InputDevices/res/values-sq/strings.xml
+++ b/packages/InputDevices/res/values-sq/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolisht"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Gjeorgjisht"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Tajlandisht (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"Tajlandisht (Pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-sr/strings.xml b/packages/InputDevices/res/values-sr/strings.xml
index 2f500138f..0b434d7 100644
--- a/packages/InputDevices/res/values-sr/strings.xml
+++ b/packages/InputDevices/res/values-sr/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"монголска"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"грузијска"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"тајски (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"тајски (Pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-sv/strings.xml b/packages/InputDevices/res/values-sv/strings.xml
index f29b665..3d08415 100644
--- a/packages/InputDevices/res/values-sv/strings.xml
+++ b/packages/InputDevices/res/values-sv/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"mongoliska"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"georgiska"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thai (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"thailändska (pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-sw/strings.xml b/packages/InputDevices/res/values-sw/strings.xml
index ade2c28..42714a5 100644
--- a/packages/InputDevices/res/values-sw/strings.xml
+++ b/packages/InputDevices/res/values-sw/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Kimongolia"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Kijojia"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Kithai (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"Kitai (Kipatachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-ta/strings.xml b/packages/InputDevices/res/values-ta/strings.xml
index 14a17ad..f8bc751 100644
--- a/packages/InputDevices/res/values-ta/strings.xml
+++ b/packages/InputDevices/res/values-ta/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"மங்கோலியன்"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"ஜார்ஜியன்"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"தாய் (கேட்மேனி)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"தாய் (பட்டாசொட்டே)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-te/strings.xml b/packages/InputDevices/res/values-te/strings.xml
index 676dd92..2c1c1f8 100644
--- a/packages/InputDevices/res/values-te/strings.xml
+++ b/packages/InputDevices/res/values-te/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"మంగోలియన్"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"జార్జియన్"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"థాయ్ (కెడ్మనీ)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"థాయ్ (పత్తచోత్)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-th/strings.xml b/packages/InputDevices/res/values-th/strings.xml
index 2473128..3b96226 100644
--- a/packages/InputDevices/res/values-th/strings.xml
+++ b/packages/InputDevices/res/values-th/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"ภาษามองโกเลีย"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"ภาษาจอร์เจีย"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"ไทย (เกษมณี)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"ไทย (ปัตตะโชติ)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-tl/strings.xml b/packages/InputDevices/res/values-tl/strings.xml
index cefa8ac..f0cd0f8 100644
--- a/packages/InputDevices/res/values-tl/strings.xml
+++ b/packages/InputDevices/res/values-tl/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolian"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgian"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thai (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"Thai (Pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-tr/strings.xml b/packages/InputDevices/res/values-tr/strings.xml
index ba4703c..a5c89d7 100644
--- a/packages/InputDevices/res/values-tr/strings.xml
+++ b/packages/InputDevices/res/values-tr/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Moğolca"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Gürcüce"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Tayca (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"Tayca (Pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-uk/strings.xml b/packages/InputDevices/res/values-uk/strings.xml
index c74b1c1..dd3aab8 100644
--- a/packages/InputDevices/res/values-uk/strings.xml
+++ b/packages/InputDevices/res/values-uk/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Монгольська"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Грузинська"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Тайська (кедмані)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"Тайська (паттачоте)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-ur/strings.xml b/packages/InputDevices/res/values-ur/strings.xml
index 70ce599..008cd10 100644
--- a/packages/InputDevices/res/values-ur/strings.xml
+++ b/packages/InputDevices/res/values-ur/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"منگؤلی"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"جارجیائی"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"تھائی (کیڈمینی)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"تھائی (پٹاچوٹے)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-uz/strings.xml b/packages/InputDevices/res/values-uz/strings.xml
index bd6c713..2c1c4b0 100644
--- a/packages/InputDevices/res/values-uz/strings.xml
+++ b/packages/InputDevices/res/values-uz/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongol"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Gruzin"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Tay (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"Tay (Pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-vi/strings.xml b/packages/InputDevices/res/values-vi/strings.xml
index d665f8e..b5a0b16b 100644
--- a/packages/InputDevices/res/values-vi/strings.xml
+++ b/packages/InputDevices/res/values-vi/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Tiếng Mông Cổ"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Tiếng Georgia"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Tiếng Thái (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"Tiếng Thái (Pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-zh-rCN/strings.xml b/packages/InputDevices/res/values-zh-rCN/strings.xml
index e6c19b3..97e75e6 100644
--- a/packages/InputDevices/res/values-zh-rCN/strings.xml
+++ b/packages/InputDevices/res/values-zh-rCN/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"蒙古语"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"格鲁吉亚语"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"泰语 (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"泰语 (Pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-zh-rHK/strings.xml b/packages/InputDevices/res/values-zh-rHK/strings.xml
index ee3f598..45d4b4f 100644
--- a/packages/InputDevices/res/values-zh-rHK/strings.xml
+++ b/packages/InputDevices/res/values-zh-rHK/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"蒙古文"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"格魯吉亞文"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"泰文 (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"泰文 (Pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-zh-rTW/strings.xml b/packages/InputDevices/res/values-zh-rTW/strings.xml
index b25001b..f0ea94b 100644
--- a/packages/InputDevices/res/values-zh-rTW/strings.xml
+++ b/packages/InputDevices/res/values-zh-rTW/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"蒙古文"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"喬治亞文"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"泰文 (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"泰文 (Pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-zu/strings.xml b/packages/InputDevices/res/values-zu/strings.xml
index 8f07a9b..079b841 100644
--- a/packages/InputDevices/res/values-zu/strings.xml
+++ b/packages/InputDevices/res/values-zu/strings.xml
@@ -51,6 +51,5 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"isi-Mongolian"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgian"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Isi-Thai (Kedmanee)"</string>
- <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
- <skip />
+ <string name="keyboard_layout_thai_pattachote" msgid="2547992342794252205">"Isi-Thai (Pattachote)"</string>
</resources>
diff --git a/packages/InputDevices/res/xml/keyboard_layouts.xml b/packages/InputDevices/res/xml/keyboard_layouts.xml
index c18d73c..d4f8f7d 100644
--- a/packages/InputDevices/res/xml/keyboard_layouts.xml
+++ b/packages/InputDevices/res/xml/keyboard_layouts.xml
@@ -94,7 +94,7 @@
android:name="keyboard_layout_swiss_german"
android:label="@string/keyboard_layout_swiss_german_label"
android:keyboardLayout="@raw/keyboard_layout_swiss_german"
- android:keyboardLocale="de-Latn-CH|gsw-Latn-CH"
+ android:keyboardLocale="de-Latn-CH,gsw-Latn-CH"
android:keyboardLayoutType="qwertz" />
<keyboard-layout
diff --git a/packages/PackageInstaller/res/values-az/strings.xml b/packages/PackageInstaller/res/values-az/strings.xml
index 8b4b68d..de59d60 100644
--- a/packages/PackageInstaller/res/values-az/strings.xml
+++ b/packages/PackageInstaller/res/values-az/strings.xml
@@ -72,7 +72,7 @@
<string name="uninstall_keep_data" msgid="7002379587465487550">"Tətbiq datasının <xliff:g id="SIZE">%1$s</xliff:g> hissəsini saxlayın."</string>
<string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Bu tətbiq silinsin?"</string>
<string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Bu tətbiqi sistemdən silmək istəyirsiniz? <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> kopya da silinəcək."</string>
- <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Bu tətbiqi şəxsi məkandan silmək istəyirsiniz?"</string>
+ <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Bu tətbiqi məxfi məkandan silmək istəyirsiniz?"</string>
<string name="uninstalling_notification_channel" msgid="840153394325714653">"İşləyən sistemlər silinmələr"</string>
<string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Uğursuz olan sistemlər silinmələr"</string>
<string name="uninstalling" msgid="8709566347688966845">"Sistemdən silinir..."</string>
diff --git a/packages/PackageInstaller/res/values-be/strings.xml b/packages/PackageInstaller/res/values-be/strings.xml
index d1cb7d0..a4c3097 100644
--- a/packages/PackageInstaller/res/values-be/strings.xml
+++ b/packages/PackageInstaller/res/values-be/strings.xml
@@ -72,7 +72,7 @@
<string name="uninstall_keep_data" msgid="7002379587465487550">"Захаваць даныя праграмы (<xliff:g id="SIZE">%1$s</xliff:g>)."</string>
<string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Выдаліць гэту праграму?"</string>
<string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Выдаліць гэту праграму? Таксама будзе выдалены клон \"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>\"."</string>
- <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Выдаліць гэту праграму з прыватнай аўдыторыі?"</string>
+ <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Выдаліць гэту праграму з прыватнай прасторы?"</string>
<string name="uninstalling_notification_channel" msgid="840153394325714653">"Актыўныя выдаленні"</string>
<string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Нявыкананыя выдаленні"</string>
<string name="uninstalling" msgid="8709566347688966845">"Ідзе выдаленне…"</string>
diff --git a/packages/PackageInstaller/res/values-bn/strings.xml b/packages/PackageInstaller/res/values-bn/strings.xml
index 231f451..d7ad522 100644
--- a/packages/PackageInstaller/res/values-bn/strings.xml
+++ b/packages/PackageInstaller/res/values-bn/strings.xml
@@ -72,7 +72,7 @@
<string name="uninstall_keep_data" msgid="7002379587465487550">"অ্যাপ ডেটার মধ্যে <xliff:g id="SIZE">%1$s</xliff:g> রেখে দিন।"</string>
<string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"আপনি এই অ্যাপ মুছে ফেলতে চান?"</string>
<string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"আপনি এই অ্যাপ আনইনস্টল করতে চান? <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ক্লোনও মুছে ফেলা হবে।"</string>
- <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"আপনার ব্যক্তিগত স্পেস থেকে এই অ্যাপ আনইনস্টল করতে চান?"</string>
+ <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"আপনার প্রাইভেট স্পেস থেকে এই অ্যাপ আনইনস্টল করতে চান?"</string>
<string name="uninstalling_notification_channel" msgid="840153394325714653">"আনইনস্টল করা হচ্ছে"</string>
<string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"আনইনস্টল করা যায়নি"</string>
<string name="uninstalling" msgid="8709566347688966845">"আনইনস্টল করা হচ্ছে…"</string>
diff --git a/packages/PackageInstaller/res/values-de/strings.xml b/packages/PackageInstaller/res/values-de/strings.xml
index ef9d207..21651ba1 100644
--- a/packages/PackageInstaller/res/values-de/strings.xml
+++ b/packages/PackageInstaller/res/values-de/strings.xml
@@ -72,7 +72,7 @@
<string name="uninstall_keep_data" msgid="7002379587465487550">"<xliff:g id="SIZE">%1$s</xliff:g> an App-Daten behalten."</string>
<string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Möchtest du diese App löschen?"</string>
<string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Möchtest du diese App deinstallieren? Der <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>-Klon wird ebenfalls gelöscht."</string>
- <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Möchtest du diese App in deinem privaten Bereich deinstallieren?"</string>
+ <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Möchtest du diese App deinstallieren und damit aus deinem vertraulichen Bereich entfernen?"</string>
<string name="uninstalling_notification_channel" msgid="840153394325714653">"Laufende Deinstallationen"</string>
<string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Fehlgeschlagene Deinstallationen"</string>
<string name="uninstalling" msgid="8709566347688966845">"Wird deinstalliert..."</string>
diff --git a/packages/PackageInstaller/res/values-fa/strings.xml b/packages/PackageInstaller/res/values-fa/strings.xml
index 288653a..e2ab36f 100644
--- a/packages/PackageInstaller/res/values-fa/strings.xml
+++ b/packages/PackageInstaller/res/values-fa/strings.xml
@@ -72,7 +72,7 @@
<string name="uninstall_keep_data" msgid="7002379587465487550">"<xliff:g id="SIZE">%1$s</xliff:g> از دادههای برنامه را نگهدارید."</string>
<string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"میخواهید این برنامه را حذف کنید؟"</string>
<string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"میخواهید این برنامه را حذف نصب کنید؟ همسانه <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> هم حذف خواهد شد."</string>
- <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"میخواهید این برنامه از فضای خصوصی حذف نصب شود؟"</string>
+ <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"میخواهید این برنامه را از فضای خصوصی حذف نصب کنید؟"</string>
<string name="uninstalling_notification_channel" msgid="840153394325714653">"حذفنصبهای درحال انجام"</string>
<string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"حذفنصبهای ناموفق"</string>
<string name="uninstalling" msgid="8709566347688966845">"درحال حذف نصب..."</string>
@@ -122,7 +122,7 @@
<string name="unarchive_action_required_body" msgid="1679431572983989231">"برای بازیابی این برنامه، مراحل بعدی را دنبال کنید"</string>
<string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> غیرفعال است"</string>
<string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"برای بازیابی این برنامه، <xliff:g id="INSTALLERNAME">%1$s</xliff:g> را در «تنظیمات» فعال کنید"</string>
- <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> حذف نصب شده است"</string>
+ <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> حذف نصب شده است"</string>
<string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"برای بازیابی این برنامه، باید <xliff:g id="INSTALLERNAME">%1$s</xliff:g> را نصب کنید"</string>
<string name="unarchive_action_required_continue" msgid="5711202111224184257">"ادامه دادن"</string>
<string name="unarchive_clear_storage_button" msgid="1549537154535608744">"پاک کردن فضای ذخیرهسازی"</string>
diff --git a/packages/PackageInstaller/res/values-fr-rCA/strings.xml b/packages/PackageInstaller/res/values-fr-rCA/strings.xml
index de38df3..60075e6 100644
--- a/packages/PackageInstaller/res/values-fr-rCA/strings.xml
+++ b/packages/PackageInstaller/res/values-fr-rCA/strings.xml
@@ -72,13 +72,13 @@
<string name="uninstall_keep_data" msgid="7002379587465487550">"Garder <xliff:g id="SIZE">%1$s</xliff:g> de données d\'application."</string>
<string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Voulez-vous supprimer cette application?"</string>
<string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Voulez-vous désinstaller cette application? Le clone de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> sera aussi supprimé."</string>
- <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Voulez-vous désinstaller cette application de votre Espace privé?"</string>
+ <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Voulez-vous désinstaller cette appli de votre espace privé?"</string>
<string name="uninstalling_notification_channel" msgid="840153394325714653">"Désinstallations en cours…"</string>
<string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Désinstallations échouées"</string>
<string name="uninstalling" msgid="8709566347688966845">"Désinstallation en cours…"</string>
<string name="uninstalling_app" msgid="8866082646836981397">"Désinstallation de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> en cours…"</string>
<string name="uninstall_done" msgid="439354138387969269">"Désinstallation terminée."</string>
- <string name="uninstall_done_app" msgid="4588850984473605768">"L\'application <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> a bien été désinstallée"</string>
+ <string name="uninstall_done_app" msgid="4588850984473605768">"L\'appli <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> a bien été désinstallée"</string>
<string name="uninstall_done_clone_app" msgid="5578308154544195413">"Le clone de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> a été supprimé"</string>
<string name="uninstall_failed" msgid="1847750968168364332">"Échec de la désinstallation."</string>
<string name="uninstall_failed_app" msgid="5506028705017601412">"La désinstallation de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> n\'a pas réussi."</string>
diff --git a/packages/PackageInstaller/res/values-hr/strings.xml b/packages/PackageInstaller/res/values-hr/strings.xml
index 92ad7f0..30f3f49 100644
--- a/packages/PackageInstaller/res/values-hr/strings.xml
+++ b/packages/PackageInstaller/res/values-hr/strings.xml
@@ -78,7 +78,7 @@
<string name="uninstalling" msgid="8709566347688966845">"Deinstaliranje…"</string>
<string name="uninstalling_app" msgid="8866082646836981397">"Deinstaliranje aplikacije <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
<string name="uninstall_done" msgid="439354138387969269">"Deinstalacija je završena."</string>
- <string name="uninstall_done_app" msgid="4588850984473605768">"Aplikacija <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> deinstalirana"</string>
+ <string name="uninstall_done_app" msgid="4588850984473605768">"Aplikacija <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> je deinstalirana"</string>
<string name="uninstall_done_clone_app" msgid="5578308154544195413">"Izbrisan je klon paketa <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
<string name="uninstall_failed" msgid="1847750968168364332">"Deinstalacija nije uspjela."</string>
<string name="uninstall_failed_app" msgid="5506028705017601412">"Deinstaliranje aplikacije <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> nije uspjelo."</string>
diff --git a/packages/PackageInstaller/res/values-hy/strings.xml b/packages/PackageInstaller/res/values-hy/strings.xml
index d9fb570..ed5323f 100644
--- a/packages/PackageInstaller/res/values-hy/strings.xml
+++ b/packages/PackageInstaller/res/values-hy/strings.xml
@@ -63,7 +63,7 @@
<string name="archive_application_text_all_users" msgid="3151229641681672580">"Արխիվացնե՞լ այս հավելվածը բոլոր օգտատերերի համար։ Ձեր անձնական տվյալները կպահվեն"</string>
<string name="archive_application_text_current_user_work_profile" msgid="1450487362134779752">"Արխիվացնե՞լ այս հավելվածը ձեր աշխատանքային պրոֆիլում։ Ձեր անձնական տվյալները կպահվեն"</string>
<string name="archive_application_text_user" msgid="2586558895535581451">"Արխիվացնե՞լ այս հավելվածը <xliff:g id="USERNAME">%1$s</xliff:g> օգտատիրոջ համար։ Ձեր անձնական տվյալները կպահվեն"</string>
- <string name="archive_application_text_current_user_private_profile" msgid="1958423158655599132">"Արխիվացնե՞լ այս հավելվածը ձեր անձնական տարածքից։ Ձեր անձնական տվյալները կպահվեն"</string>
+ <string name="archive_application_text_current_user_private_profile" msgid="1958423158655599132">"Արխիվացնե՞լ այս հավելվածը ձեր մասնավոր տարածքից։ Ձեր անձնական տվյալները կպահվեն"</string>
<string name="uninstall_application_text_all_users" msgid="575491774380227119">"Ապատեղադրե՞լ այս հավելվածը "<b>"բոլոր"</b>" օգտատերերի համար: Հավելվածը և դրա տվյալները կհեռացվեն սարքի "<b>"բոլոր"</b>" օգտատերերից:"</string>
<string name="uninstall_application_text_user" msgid="498072714173920526">"Ապատեղադրե՞լ այս հավելվածը <xliff:g id="USERNAME">%1$s</xliff:g> օգտատիրոջ համար:"</string>
<string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Հեռացնե՞լ այս հավելվածը ձեր աշխատանքային պրոֆիլից"</string>
@@ -72,7 +72,7 @@
<string name="uninstall_keep_data" msgid="7002379587465487550">"Չհեռացնել հավելվածների տվյալները (<xliff:g id="SIZE">%1$s</xliff:g>):"</string>
<string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Ջնջե՞լ այս հավելվածը"</string>
<string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Ապատեղադրե՞լ այս հավելվածը։ <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>-ի կլոնը նույնպես կջնջվի։"</string>
- <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Ապատեղադրե՞լ այս հավելվածը ձեր անձնական տարածքից"</string>
+ <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Ապատեղադրե՞լ այս հավելվածը ձեր մասնավոր տարածքից"</string>
<string name="uninstalling_notification_channel" msgid="840153394325714653">"Ընթացիկ ապատեղադրումներ"</string>
<string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Ձախողված ապատեղադրումներ"</string>
<string name="uninstalling" msgid="8709566347688966845">"Ապատեղադրվում է…"</string>
diff --git a/packages/PackageInstaller/res/values-in/strings.xml b/packages/PackageInstaller/res/values-in/strings.xml
index 8115b50..36cb404 100644
--- a/packages/PackageInstaller/res/values-in/strings.xml
+++ b/packages/PackageInstaller/res/values-in/strings.xml
@@ -72,7 +72,7 @@
<string name="uninstall_keep_data" msgid="7002379587465487550">"Pertahankan data aplikasi sebesar <xliff:g id="SIZE">%1$s</xliff:g>."</string>
<string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Ingin menghapus aplikasi ini?"</string>
<string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Ingin meng-uninstal aplikasi ini? Clone <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> juga akan dihapus."</string>
- <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Ingin meng-uninstal aplikasi ini dari ruang pribadi?"</string>
+ <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Ingin meng-uninstal aplikasi ini dari ruang privasi?"</string>
<string name="uninstalling_notification_channel" msgid="840153394325714653">"Menjalankan proses uninstal"</string>
<string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Proses uninstal yang gagal"</string>
<string name="uninstalling" msgid="8709566347688966845">"Meng-uninstal..."</string>
diff --git a/packages/PackageInstaller/res/values-is/strings.xml b/packages/PackageInstaller/res/values-is/strings.xml
index 9d24d185..80ace23 100644
--- a/packages/PackageInstaller/res/values-is/strings.xml
+++ b/packages/PackageInstaller/res/values-is/strings.xml
@@ -72,7 +72,7 @@
<string name="uninstall_keep_data" msgid="7002379587465487550">"Halda <xliff:g id="SIZE">%1$s</xliff:g> af forritagögnum."</string>
<string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Viltu eyða þessu forriti?"</string>
<string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Viltu fjarlægja þetta forrit? Afriti af <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> verður einnig eytt."</string>
- <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Viltu fjarlægja þetta forrit úr einkarýminu?"</string>
+ <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Viltu fjarlægja þetta forrit úr leynirýminu?"</string>
<string name="uninstalling_notification_channel" msgid="840153394325714653">"Fjarlægingar í gangi"</string>
<string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Fjarlægingar sem mistókust"</string>
<string name="uninstalling" msgid="8709566347688966845">"Fjarlægir…"</string>
diff --git a/packages/PackageInstaller/res/values-ka/strings.xml b/packages/PackageInstaller/res/values-ka/strings.xml
index 29cc33f..594848a 100644
--- a/packages/PackageInstaller/res/values-ka/strings.xml
+++ b/packages/PackageInstaller/res/values-ka/strings.xml
@@ -72,7 +72,7 @@
<string name="uninstall_keep_data" msgid="7002379587465487550">"შენარჩუნდეს აპების მონაცემების <xliff:g id="SIZE">%1$s</xliff:g>."</string>
<string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"გსურთ ამ აპის წაშლა?"</string>
<string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"გსურთ ამ აპის დეინსტალაცია? <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> კლონი ასევე წაიშლება."</string>
- <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"გსურთ ამ აპის დეინსტალაცია თქვენი პირადი სივრციდან?"</string>
+ <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"გსურთ ამ აპის დეინსტალაცია თქვენი კერძო სივრციდან?"</string>
<string name="uninstalling_notification_channel" msgid="840153394325714653">"გაშვებული დეინსტალაციები"</string>
<string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"შეუსრულებელი დეინსტალაციები"</string>
<string name="uninstalling" msgid="8709566347688966845">"მიმდინარეობს დეინსტალაცია…"</string>
diff --git a/packages/PackageInstaller/res/values-kk/strings.xml b/packages/PackageInstaller/res/values-kk/strings.xml
index a13cc4b..182aaa6 100644
--- a/packages/PackageInstaller/res/values-kk/strings.xml
+++ b/packages/PackageInstaller/res/values-kk/strings.xml
@@ -72,7 +72,7 @@
<string name="uninstall_keep_data" msgid="7002379587465487550">"Қолданба деректерін (<xliff:g id="SIZE">%1$s</xliff:g>) сақтау."</string>
<string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Осы қолданба жойылсын ба?"</string>
<string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Осы қолданба жойылсын ба? <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> клоны да жойылады."</string>
- <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Осы құрылғыны жеке бөлмеңізден жойғыңыз келе ме?"</string>
+ <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Осы қолданбаны құпия кеңістіктен жою керек пе?"</string>
<string name="uninstalling_notification_channel" msgid="840153394325714653">"Орындалып жатқан жою процестері"</string>
<string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Сәтсіз жою әрекеттері"</string>
<string name="uninstalling" msgid="8709566347688966845">"Жойылуда…"</string>
diff --git a/packages/PackageInstaller/res/values-km/strings.xml b/packages/PackageInstaller/res/values-km/strings.xml
index 2ec2f4d..ea9a015 100644
--- a/packages/PackageInstaller/res/values-km/strings.xml
+++ b/packages/PackageInstaller/res/values-km/strings.xml
@@ -72,7 +72,7 @@
<string name="uninstall_keep_data" msgid="7002379587465487550">"រក្សាទុកទិន្នន័យកម្មវិធីទំហំ <xliff:g id="SIZE">%1$s</xliff:g>។"</string>
<string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"តើអ្នកចង់លុបកម្មវិធីនេះដែរឬទេ?"</string>
<string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"តើអ្នកចង់លុបកម្មវិធីនេះដែរឬទេ? ក្លូន <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ក៏នឹងត្រូវបានលុបផងដែរ។"</string>
- <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"តើអ្នកចង់លុបកម្មវិធីនេះចេញពី private space របស់អ្នកដែរទេ?"</string>
+ <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"តើអ្នកចង់លុបកម្មវិធីនេះចេញពីលំហឯកជនរបស់អ្នកដែរទេ?"</string>
<string name="uninstalling_notification_channel" msgid="840153394325714653">"កំពុងដំណើរការការលុប"</string>
<string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"ការលុបដែលបរាជ័យ"</string>
<string name="uninstalling" msgid="8709566347688966845">"កំពុងលុប…"</string>
diff --git a/packages/PackageInstaller/res/values-mn/strings.xml b/packages/PackageInstaller/res/values-mn/strings.xml
index ab2bb9f..3748f17 100644
--- a/packages/PackageInstaller/res/values-mn/strings.xml
+++ b/packages/PackageInstaller/res/values-mn/strings.xml
@@ -72,7 +72,7 @@
<string name="uninstall_keep_data" msgid="7002379587465487550">"Аппын өгөгдлийн <xliff:g id="SIZE">%1$s</xliff:g>-г үлдээнэ үү."</string>
<string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Та энэ аппыг устгахыг хүсэж байна уу?"</string>
<string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Та энэ аппыг устгахыг хүсэж байна уу? <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>-н хувилалыг мөн устгана."</string>
- <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Та энэ аппыг хувийн орон зайнаасаа устгахдаа итгэлтэй байна уу?"</string>
+ <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Та энэ аппыг хаалттай орон зайнаасаа устгахдаа итгэлтэй байна уу?"</string>
<string name="uninstalling_notification_channel" msgid="840153394325714653">"Устгаж байна"</string>
<string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Устгаж чадсангүй"</string>
<string name="uninstalling" msgid="8709566347688966845">"Устгаж байна…"</string>
diff --git a/packages/PackageInstaller/res/values-ms/strings.xml b/packages/PackageInstaller/res/values-ms/strings.xml
index e4d321c..67e10ad 100644
--- a/packages/PackageInstaller/res/values-ms/strings.xml
+++ b/packages/PackageInstaller/res/values-ms/strings.xml
@@ -63,7 +63,7 @@
<string name="archive_application_text_all_users" msgid="3151229641681672580">"Arkibkan apl ini untuk semua pengguna? Data peribadi anda akan disimpan"</string>
<string name="archive_application_text_current_user_work_profile" msgid="1450487362134779752">"Arkibkan apl ini dalam profil kerja anda? Data peribadi anda akan disimpan"</string>
<string name="archive_application_text_user" msgid="2586558895535581451">"Arkibkan apl ini untuk <xliff:g id="USERNAME">%1$s</xliff:g>? Data peribadi anda akan disimpan"</string>
- <string name="archive_application_text_current_user_private_profile" msgid="1958423158655599132">"Adakah anda mahu mengarkibkan apl ini daripada ruang peribadi anda? Data peribadi anda akan disimpan"</string>
+ <string name="archive_application_text_current_user_private_profile" msgid="1958423158655599132">"Adakah anda mahu mengarkibkan apl ini daripada ruang persendirian anda? Data peribadi anda akan disimpan"</string>
<string name="uninstall_application_text_all_users" msgid="575491774380227119">"Adakah anda mahu menyahpasang apl ini untuk "<b>"semua"</b>" pengguna? Aplikasi dan datanya akan dialih keluar daripada "<b>"semua"</b>" pengguna pada peranti."</string>
<string name="uninstall_application_text_user" msgid="498072714173920526">"Adakah anda ingin menyahpasang apl ini untuk pengguna <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
<string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Adakah anda mahu menyahpasang apl ini daripada profil kerja anda?"</string>
@@ -72,7 +72,7 @@
<string name="uninstall_keep_data" msgid="7002379587465487550">"Simpan <xliff:g id="SIZE">%1$s</xliff:g> data apl."</string>
<string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Adakah anda mahu memadamkan apl ini?"</string>
<string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Adakah anda mahu menyahpasang apl ini? Klon <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> juga akan dipadamkan."</string>
- <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Adakah anda mahu menyahpasang apl ini daripada ruang peribadi anda?"</string>
+ <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Adakah anda mahu menyahpasang apl ini daripada ruang persendirian anda?"</string>
<string name="uninstalling_notification_channel" msgid="840153394325714653">"Penyahpasangan yang sedang berjalan"</string>
<string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Penyahpasangan yang gagal"</string>
<string name="uninstalling" msgid="8709566347688966845">"Menyahpasang…"</string>
diff --git a/packages/PackageInstaller/res/values-or/strings.xml b/packages/PackageInstaller/res/values-or/strings.xml
index 8bf3225..b99bf1a 100644
--- a/packages/PackageInstaller/res/values-or/strings.xml
+++ b/packages/PackageInstaller/res/values-or/strings.xml
@@ -78,7 +78,7 @@
<string name="uninstalling" msgid="8709566347688966845">"ଅନ୍ଇନଷ୍ଟଲ୍ କରାଯାଉଛି…"</string>
<string name="uninstalling_app" msgid="8866082646836981397">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ଅନଇନଷ୍ଟଲ୍ କରାଯାଉଛି…"</string>
<string name="uninstall_done" msgid="439354138387969269">"ଅନଇନଷ୍ଟଲ୍ ହୋଇଗଲା।"</string>
- <string name="uninstall_done_app" msgid="4588850984473605768">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>କୁ ଅନଇନଷ୍ଟଲ୍ କରାଗଲା"</string>
+ <string name="uninstall_done_app" msgid="4588850984473605768">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>କୁ ଅନଇନଷ୍ଟଲ କରାଯାଇଛି"</string>
<string name="uninstall_done_clone_app" msgid="5578308154544195413">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>ର କ୍ଲୋନକୁ ଡିଲିଟ କରାଯାଇଛି"</string>
<string name="uninstall_failed" msgid="1847750968168364332">"ଅନଇନଷ୍ଟଲ୍ କରିହେଲା ନାହିଁ।"</string>
<string name="uninstall_failed_app" msgid="5506028705017601412">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ଅନଇନଷ୍ଟଲ୍ କରିବା ସଫଳ ହେଲାନାହିଁ।"</string>
diff --git a/packages/PackageInstaller/res/values-pa/strings.xml b/packages/PackageInstaller/res/values-pa/strings.xml
index 34a0945..1db92a0 100644
--- a/packages/PackageInstaller/res/values-pa/strings.xml
+++ b/packages/PackageInstaller/res/values-pa/strings.xml
@@ -72,7 +72,7 @@
<string name="uninstall_keep_data" msgid="7002379587465487550">"<xliff:g id="SIZE">%1$s</xliff:g> ਐਪ ਡਾਟਾ ਰੱਖੋ।"</string>
<string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"ਕੀ ਤੁਸੀਂ ਇਸ ਐਪ ਨੂੰ ਮਿਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ?"</string>
<string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"ਕੀ ਤੁਸੀਂ ਇਸ ਐਪ ਨੂੰ ਅਣਸਥਾਪਤ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ? <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ਦੇ ਕਲੋਨ ਨੂੰ ਵੀ ਮਿਟਾਇਆ ਜਾਵੇਗਾ।"</string>
- <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"ਕੀ ਤੁਸੀਂ ਇਸ ਐਪ ਨੂੰ ਆਪਣੇ ਨਿੱਜੀ ਸਪੇਸ ਤੋਂ ਅਣਸਥਾਪਤ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?"</string>
+ <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"ਕੀ ਤੁਸੀਂ ਇਸ ਐਪ ਨੂੰ ਆਪਣੀ ਪ੍ਰਾਈਵੇਟ ਸਪੇਸ ਤੋਂ ਅਣਸਥਾਪਤ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?"</string>
<string name="uninstalling_notification_channel" msgid="840153394325714653">"ਚੱਲ ਰਹੀਆਂ ਅਣਸਥਾਪਨਾਵਾਂ"</string>
<string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"ਅਸਫਲ ਅਣਸਥਾਪਨਾਵਾਂ"</string>
<string name="uninstalling" msgid="8709566347688966845">"ਅਣਸਥਾਪਤ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ…"</string>
diff --git a/packages/PackageInstaller/res/values-pl/strings.xml b/packages/PackageInstaller/res/values-pl/strings.xml
index 22a78e3..0f762c7 100644
--- a/packages/PackageInstaller/res/values-pl/strings.xml
+++ b/packages/PackageInstaller/res/values-pl/strings.xml
@@ -72,7 +72,7 @@
<string name="uninstall_keep_data" msgid="7002379587465487550">"Zachowaj <xliff:g id="SIZE">%1$s</xliff:g> danych aplikacji."</string>
<string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Chcesz usunąć tę aplikację?"</string>
<string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Chcesz odinstalować tę aplikację? Klon aplikacji <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> również zostanie usunięty."</string>
- <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Chcesz odinstalować tę aplikację ze swojego obszaru prywatnego?"</string>
+ <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Chcesz odinstalować tę aplikację ze swojej przestrzeni prywatnej?"</string>
<string name="uninstalling_notification_channel" msgid="840153394325714653">"Aktywne odinstalowania"</string>
<string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Nieudane odinstalowania"</string>
<string name="uninstalling" msgid="8709566347688966845">"Odinstalowuję…"</string>
diff --git a/packages/PackageInstaller/res/values-sl/strings.xml b/packages/PackageInstaller/res/values-sl/strings.xml
index 05b826f..69d954d 100644
--- a/packages/PackageInstaller/res/values-sl/strings.xml
+++ b/packages/PackageInstaller/res/values-sl/strings.xml
@@ -78,7 +78,7 @@
<string name="uninstalling" msgid="8709566347688966845">"Odstranjevanje …"</string>
<string name="uninstalling_app" msgid="8866082646836981397">"Odmeščanje aplikacije <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> …"</string>
<string name="uninstall_done" msgid="439354138387969269">"Odstranitev je končana."</string>
- <string name="uninstall_done_app" msgid="4588850984473605768">"Aplikacija <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> je bila odstranjena."</string>
+ <string name="uninstall_done_app" msgid="4588850984473605768">"Aplikacija <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> je bila odmeščena."</string>
<string name="uninstall_done_clone_app" msgid="5578308154544195413">"Klonirana aplikacija <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> je izbrisana"</string>
<string name="uninstall_failed" msgid="1847750968168364332">"Odstranitev ni uspela."</string>
<string name="uninstall_failed_app" msgid="5506028705017601412">"Odmeščanje aplikacije <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ni uspelo."</string>
diff --git a/packages/PackageInstaller/res/values-tr/strings.xml b/packages/PackageInstaller/res/values-tr/strings.xml
index 0af2352..006ad52 100644
--- a/packages/PackageInstaller/res/values-tr/strings.xml
+++ b/packages/PackageInstaller/res/values-tr/strings.xml
@@ -72,7 +72,7 @@
<string name="uninstall_keep_data" msgid="7002379587465487550">"Uygulama verilerinin <xliff:g id="SIZE">%1$s</xliff:g> kadarını sakla."</string>
<string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Bu uygulamayı silmek istiyor musunuz?"</string>
<string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Bu uygulamanın yüklemesini kaldırmak istiyor musunuz? <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> klonu da silinecektir."</string>
- <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Bu uygulamanın gizli alanınızdaki yüklemesini kaldırmak istiyor musunuz?"</string>
+ <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Bu uygulamanın özel alanınızdaki yüklemesini kaldırmak istiyor musunuz?"</string>
<string name="uninstalling_notification_channel" msgid="840153394325714653">"Devam eden yükleme kaldırma işlemleri"</string>
<string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Başarısız yükleme kaldırma işlemleri"</string>
<string name="uninstalling" msgid="8709566347688966845">"Yükleme kaldırılıyor…"</string>
diff --git a/packages/PackageInstaller/res/values-ur/strings.xml b/packages/PackageInstaller/res/values-ur/strings.xml
index 444fdd7..c73b79a 100644
--- a/packages/PackageInstaller/res/values-ur/strings.xml
+++ b/packages/PackageInstaller/res/values-ur/strings.xml
@@ -78,7 +78,7 @@
<string name="uninstalling" msgid="8709566347688966845">"اَن انسٹال ہو رہا ہے…"</string>
<string name="uninstalling_app" msgid="8866082646836981397">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ان انسٹال ہو رہا ہے…"</string>
<string name="uninstall_done" msgid="439354138387969269">"اَن انسٹال مکمل ہو گیا۔"</string>
- <string name="uninstall_done_app" msgid="4588850984473605768">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> اَن انسٹال ہو گیا"</string>
+ <string name="uninstall_done_app" msgid="4588850984473605768">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> اَن انسٹال ہو گیا"</string>
<string name="uninstall_done_clone_app" msgid="5578308154544195413">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> کا کلون حذف کر دیا گیا ہے"</string>
<string name="uninstall_failed" msgid="1847750968168364332">"اَن انسٹال ناکام ہو گیا۔"</string>
<string name="uninstall_failed_app" msgid="5506028705017601412">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> کو ان انسٹال کرنا ناکام ہو گیا۔"</string>
@@ -122,7 +122,7 @@
<string name="unarchive_action_required_body" msgid="1679431572983989231">"اس ایپ کو بحال کرنے کے لیے اگلے مراحل کی پیروی کریں"</string>
<string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> غیر فعال ہے"</string>
<string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"اس ایپ کو بحال کرنے کے لیے، ترتیبات میں <xliff:g id="INSTALLERNAME">%1$s</xliff:g> کو فعال کریں"</string>
- <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> اَن انسٹال ہو گیا ہے"</string>
+ <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> اَن انسٹال ہو گیا ہے"</string>
<string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"اس ایپ کو بحال کرنے کے لیے، آپ کو <xliff:g id="INSTALLERNAME">%1$s</xliff:g> انسٹال کرنا ہوگا"</string>
<string name="unarchive_action_required_continue" msgid="5711202111224184257">"جاری رکھیں"</string>
<string name="unarchive_clear_storage_button" msgid="1549537154535608744">"اسٹوریج صاف کریں"</string>
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/InstallFailed.java b/packages/PackageInstaller/src/com/android/packageinstaller/InstallFailed.java
index eef21991..c96644c 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/InstallFailed.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/InstallFailed.java
@@ -23,23 +23,23 @@
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
-import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager;
-import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
-
import androidx.annotation.Nullable;
/**
* Installation failed: Return status code to the caller or display failure UI to user
*/
public class InstallFailed extends Activity {
+
private static final String LOG_TAG = InstallFailed.class.getSimpleName();
- /** Label of the app that failed to install */
+ /**
+ * Label of the app that failed to install
+ */
private CharSequence mLabel;
private AlertDialog mDialog;
@@ -80,29 +80,29 @@
setFinishOnTouchOutside(true);
- int statusCode = getIntent().getIntExtra(PackageInstaller.EXTRA_STATUS,
- PackageInstaller.STATUS_FAILURE);
+ Intent intent = getIntent();
+ int statusCode = intent.getIntExtra(PackageInstaller.EXTRA_STATUS,
+ PackageInstaller.STATUS_FAILURE);
+ boolean returnResult = intent.getBooleanExtra(Intent.EXTRA_RETURN_RESULT, false);
- if (getIntent().getBooleanExtra(Intent.EXTRA_RETURN_RESULT, false)) {
- int legacyStatus = getIntent().getIntExtra(PackageInstaller.EXTRA_LEGACY_STATUS,
- PackageManager.INSTALL_FAILED_INTERNAL_ERROR);
+ if (returnResult) {
+ int legacyStatus = intent.getIntExtra(PackageInstaller.EXTRA_LEGACY_STATUS,
+ PackageManager.INSTALL_FAILED_INTERNAL_ERROR);
// Return result if requested
Intent result = new Intent();
result.putExtra(Intent.EXTRA_INSTALL_RESULT, legacyStatus);
setResult(Activity.RESULT_FIRST_USER, result);
finish();
- } else {
- Intent intent = getIntent();
- ApplicationInfo appInfo = intent
- .getParcelableExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO);
- Uri packageURI = intent.getData();
+ } else if (statusCode != PackageInstaller.STATUS_FAILURE_ABORTED) {
+ // statusCode will be STATUS_FAILURE_ABORTED if the update-owner confirmation dialog was
+ // dismissed by the user. We don't want to show a InstallFailed dialog in this case.
+ // If the user denies install permission for normal installs, this dialog will never be
+ // triggered as the status code is returned from PackageInstallerActivity.java
// Set header icon and title
- PackageUtil.AppSnippet as;
- PackageManager pm = getPackageManager();
- as = intent.getParcelableExtra(PackageInstallerActivity.EXTRA_APP_SNIPPET,
- PackageUtil.AppSnippet.class);
+ PackageUtil.AppSnippet as = intent.getParcelableExtra(
+ PackageInstallerActivity.EXTRA_APP_SNIPPET, PackageUtil.AppSnippet.class);
// Store label for dialog
mLabel = as.label;
@@ -127,6 +127,8 @@
// Get status messages
setExplanationFromErrorCode(statusCode);
+ } else {
+ finish();
}
}
@@ -135,6 +137,7 @@
* "manage applications" settings page.
*/
public static class OutOfSpaceDialog extends DialogFragment {
+
private InstallFailed mActivity;
@Override
@@ -147,16 +150,16 @@
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
return new AlertDialog.Builder(mActivity)
- .setTitle(R.string.out_of_space_dlg_title)
- .setMessage(getString(R.string.out_of_space_dlg_text, mActivity.mLabel))
- .setPositiveButton(R.string.manage_applications, (dialog, which) -> {
- // launch manage applications
- Intent intent = new Intent("android.intent.action.MANAGE_PACKAGE_STORAGE");
- startActivity(intent);
- mActivity.finish();
- })
- .setNegativeButton(R.string.cancel, (dialog, which) -> mActivity.finish())
- .create();
+ .setTitle(R.string.out_of_space_dlg_title)
+ .setMessage(getString(R.string.out_of_space_dlg_text, mActivity.mLabel))
+ .setPositiveButton(R.string.manage_applications, (dialog, which) -> {
+ // launch manage applications
+ Intent intent = new Intent("android.intent.action.MANAGE_PACKAGE_STORAGE");
+ startActivity(intent);
+ mActivity.finish();
+ })
+ .setNegativeButton(R.string.cancel, (dialog, which) -> mActivity.finish())
+ .create();
}
@Override
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java b/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java
index 1a6c2bb..59a511d 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java
@@ -30,6 +30,8 @@
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
import android.util.Log;
import android.view.View;
import android.widget.Button;
@@ -91,8 +93,11 @@
// ContentResolver.SCHEME_FILE
// STAGED_SESSION_ID extra contains an ID of a previously staged install session.
final File sourceFile = new File(mPackageURI.getPath());
- PackageUtil.AppSnippet as = getIntent()
- .getParcelableExtra(EXTRA_APP_SNIPPET, PackageUtil.AppSnippet.class);
+
+ // Dialogs displayed while changing update-owner have a blank icon. To fix this,
+ // fetch the appSnippet from the source file again
+ PackageUtil.AppSnippet as = PackageUtil.getAppSnippet(this, appInfo, sourceFile);
+ getIntent().putExtra(EXTRA_APP_SNIPPET, as);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
@@ -244,6 +249,14 @@
super.onDestroy();
}
+ @Override
+ public void finish() {
+ if (mDialog != null) {
+ mDialog.dismiss();
+ }
+ super.finish();
+ }
+
/**
* Launch the appropriate finish activity (success or failed) for the installation result.
*
@@ -299,7 +312,11 @@
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
try {
- session.commit(pendingIntent.getIntentSender());
+ // Delay committing the session by 100ms to fix a UI glitch while displaying the
+ // Update-Owner change dialog on top of the Installing dialog
+ new Handler(Looper.getMainLooper()).postDelayed(() -> {
+ session.commit(pendingIntent.getIntentSender());
+ }, 100);
} catch (Exception e) {
Log.e(LOG_TAG, "Cannot install package: ", e);
launchFailure(PackageInstaller.STATUS_FAILURE,
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/InstallStaging.java b/packages/PackageInstaller/src/com/android/packageinstaller/InstallStaging.java
index cf2f85e..13251d8 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/InstallStaging.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/InstallStaging.java
@@ -165,7 +165,9 @@
if (mStagingTask != null) {
mStagingTask.cancel(true);
}
-
+ if (mDialog != null) {
+ mDialog.dismiss();
+ }
super.onDestroy();
}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/InstallStart.java b/packages/PackageInstaller/src/com/android/packageinstaller/InstallStart.java
index a4c6ac7..3fea599 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/InstallStart.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/InstallStart.java
@@ -193,6 +193,7 @@
if (isSessionInstall) {
nextActivity.setClass(this, PackageInstallerActivity.class);
+ nextActivity.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
} else {
Uri packageUri = intent.getData();
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
index 8bed945..e0398aa 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
@@ -176,11 +176,14 @@
}
private CharSequence getExistingUpdateOwnerLabel() {
+ return getApplicationLabel(getExistingUpdateOwner());
+ }
+
+ private String getExistingUpdateOwner() {
try {
final String packageName = mPkgInfo.packageName;
final InstallSourceInfo sourceInfo = mPm.getInstallSourceInfo(packageName);
- final String existingUpdateOwner = sourceInfo.getUpdateOwnerPackageName();
- return getApplicationLabel(existingUpdateOwner);
+ return sourceInfo.getUpdateOwnerPackageName();
} catch (NameNotFoundException e) {
return null;
}
@@ -299,6 +302,18 @@
}
private void initiateInstall() {
+ final String existingUpdateOwner = getExistingUpdateOwner();
+ if (mSessionId == SessionInfo.INVALID_ID &&
+ !TextUtils.isEmpty(existingUpdateOwner) &&
+ !TextUtils.equals(existingUpdateOwner, mOriginatingPackage)) {
+ // Since update ownership is being changed, the system will request another
+ // user confirmation shortly. Thus, we don't need to ask the user to confirm
+ // installation here.
+ startInstall();
+ return;
+ }
+
+ // Proceed with user confirmation as we are not changing the update-owner in this install.
String pkgName = mPkgInfo.packageName;
// Check if there is already a package on the device with this name
// but it has been renamed to something else.
@@ -465,10 +480,13 @@
@Override
protected void onDestroy() {
- super.onDestroy();
while (!mActiveUnknownSourcesListeners.isEmpty()) {
unregister(mActiveUnknownSourcesListeners.get(0));
}
+ if (mDialog != null) {
+ mDialog.dismiss();
+ }
+ super.onDestroy();
}
private void bindUi() {
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/v2/model/InstallRepository.kt b/packages/PackageInstaller/src/com/android/packageinstaller/v2/model/InstallRepository.kt
index f7752ff..d969d1c 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/v2/model/InstallRepository.kt
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/v2/model/InstallRepository.kt
@@ -420,25 +420,48 @@
* * If AppOP is granted and user action is required to proceed with install
* * If AppOp grant is to be requested from the user
*/
- fun requestUserConfirmation(): InstallStage {
+ fun requestUserConfirmation(): InstallStage? {
return if (isTrustedSource) {
if (localLogv) {
Log.i(LOG_TAG, "Install allowed")
}
- // Returns InstallUserActionRequired stage if install details could be successfully
- // computed, else it returns InstallAborted.
- generateConfirmationSnippet()
+ maybeDeferUserConfirmation()
} else {
val unknownSourceStage = handleUnknownSources(appOpRequestInfo)
if (unknownSourceStage.stageCode == InstallStage.STAGE_READY) {
// Source app already has appOp granted.
- generateConfirmationSnippet()
+ maybeDeferUserConfirmation()
} else {
unknownSourceStage
}
}
}
+ /**
+ * If the update-owner for the incoming app is being changed, defer confirming with the
+ * user and directly proceed with the install. The system will request another
+ * user confirmation shortly.
+ */
+ private fun maybeDeferUserConfirmation(): InstallStage? {
+ // Returns InstallUserActionRequired stage if install details could be successfully
+ // computed, else it returns InstallAborted.
+ val confirmationSnippet: InstallStage = generateConfirmationSnippet()
+
+ val existingUpdateOwner: CharSequence? = getExistingUpdateOwner(newPackageInfo!!)
+ return if (sessionId == SessionInfo.INVALID_ID &&
+ !TextUtils.isEmpty(existingUpdateOwner) &&
+ !TextUtils.equals(existingUpdateOwner, callingPackage)
+ ) {
+ // Since update ownership is being changed, the system will request another
+ // user confirmation shortly. Thus, we don't need to ask the user to confirm
+ // installation here.
+ initiateInstall()
+ null
+ } else {
+ confirmationSnippet
+ }
+ }
+
private fun generateConfirmationSnippet(): InstallStage {
val packageSource: Any?
val pendingUserActionReason: Int
@@ -639,11 +662,14 @@
}
private fun getExistingUpdateOwnerLabel(pkgInfo: PackageInfo): CharSequence? {
+ return getApplicationLabel(getExistingUpdateOwner(pkgInfo))
+ }
+
+ private fun getExistingUpdateOwner(pkgInfo: PackageInfo): String? {
return try {
val packageName = pkgInfo.packageName
val sourceInfo = packageManager.getInstallSourceInfo(packageName)
- val existingUpdateOwner = sourceInfo.updateOwnerPackageName
- getApplicationLabel(existingUpdateOwner)
+ sourceInfo.updateOwnerPackageName
} catch (e: PackageManager.NameNotFoundException) {
null
}
@@ -861,7 +887,12 @@
}
_installResult.setValue(InstallSuccess(appSnippet, shouldReturnResult, resultIntent))
} else {
- _installResult.setValue(InstallFailed(appSnippet, statusCode, legacyStatus, message))
+ if (statusCode != PackageInstaller.STATUS_FAILURE_ABORTED) {
+ _installResult.setValue(InstallFailed(appSnippet, statusCode, legacyStatus, message))
+ } else {
+ _installResult.setValue(InstallAborted(ABORT_REASON_INTERNAL_ERROR))
+ }
+
}
}
@@ -889,8 +920,8 @@
* When the identity of the install source could not be determined, user can skip checking the
* source and directly proceed with the install.
*/
- fun forcedSkipSourceCheck(): InstallStage {
- return generateConfirmationSnippet()
+ fun forcedSkipSourceCheck(): InstallStage? {
+ return maybeDeferUserConfirmation()
}
val stagingProgress: LiveData<Int>
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/v2/viewmodel/InstallViewModel.kt b/packages/PackageInstaller/src/com/android/packageinstaller/v2/viewmodel/InstallViewModel.kt
index 072fb2d..388e03f 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/v2/viewmodel/InstallViewModel.kt
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/v2/viewmodel/InstallViewModel.kt
@@ -22,6 +22,7 @@
import androidx.lifecycle.LiveData
import androidx.lifecycle.MediatorLiveData
import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.distinctUntilChanged
import com.android.packageinstaller.v2.model.InstallRepository
import com.android.packageinstaller.v2.model.InstallStage
import com.android.packageinstaller.v2.model.InstallStaging
@@ -37,6 +38,19 @@
val currentInstallStage: MutableLiveData<InstallStage>
get() = _currentInstallStage
+ init {
+ // Since installing is an async operation, we may get the install result later in time.
+ // Result of the installation will be set in InstallRepository#installResult.
+ // As such, currentInstallStage will need to add another MutableLiveData as a data source
+ _currentInstallStage.addSource(
+ repository.installResult.distinctUntilChanged()
+ ) { installStage: InstallStage? ->
+ if (installStage != null) {
+ _currentInstallStage.value = installStage
+ }
+ }
+ }
+
fun preprocessIntent(intent: Intent, callerInfo: InstallRepository.CallerInfo) {
val stage = repository.performPreInstallChecks(intent, callerInfo)
if (stage.stageCode == InstallStage.STAGE_ABORTED) {
@@ -62,12 +76,16 @@
private fun checkIfAllowedAndInitiateInstall() {
val stage = repository.requestUserConfirmation()
- _currentInstallStage.value = stage
+ if (stage != null) {
+ _currentInstallStage.value = stage
+ }
}
fun forcedSkipSourceCheck() {
val stage = repository.forcedSkipSourceCheck()
- _currentInstallStage.value = stage
+ if (stage != null) {
+ _currentInstallStage.value = stage
+ }
}
fun cleanupInstall() {
@@ -80,15 +98,7 @@
}
fun initiateInstall() {
- // Since installing is an async operation, we will get the install result later in time.
- // Result of the installation will be set in InstallRepository#mInstallResult.
- // As such, mCurrentInstallStage will need to add another MutableLiveData as a data source
repository.initiateInstall()
- _currentInstallStage.addSource(repository.installResult) { installStage: InstallStage? ->
- if (installStage != null) {
- _currentInstallStage.value = installStage
- }
- }
}
val stagedSessionId: Int
diff --git a/packages/SettingsLib/HelpUtils/res/values-fi/strings.xml b/packages/SettingsLib/HelpUtils/res/values-fi/strings.xml
index de2b100..cef5080 100644
--- a/packages/SettingsLib/HelpUtils/res/values-fi/strings.xml
+++ b/packages/SettingsLib/HelpUtils/res/values-fi/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="help_feedback_label" msgid="7106780063063027882">"Ohje ja palaute"</string>
+ <string name="help_feedback_label" msgid="7106780063063027882">"Ohjeet ja palaute"</string>
</resources>
diff --git a/packages/SettingsLib/ProfileSelector/res/values-az/strings.xml b/packages/SettingsLib/ProfileSelector/res/values-az/strings.xml
index 6469f6f..1e89937 100644
--- a/packages/SettingsLib/ProfileSelector/res/values-az/strings.xml
+++ b/packages/SettingsLib/ProfileSelector/res/values-az/strings.xml
@@ -19,5 +19,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="settingslib_category_personal" msgid="1142302328104700620">"Şəxsi"</string>
<string name="settingslib_category_work" msgid="4867750733682444676">"İş"</string>
- <string name="settingslib_category_private" msgid="5039276873477591386">"Şəxsi"</string>
+ <string name="settingslib_category_private" msgid="5039276873477591386">"Məxfi"</string>
</resources>
diff --git a/packages/SettingsLib/ProfileSelector/res/values-de/strings.xml b/packages/SettingsLib/ProfileSelector/res/values-de/strings.xml
index bb9a6a9..56f2ce1 100644
--- a/packages/SettingsLib/ProfileSelector/res/values-de/strings.xml
+++ b/packages/SettingsLib/ProfileSelector/res/values-de/strings.xml
@@ -19,5 +19,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="settingslib_category_personal" msgid="1142302328104700620">"Privat"</string>
<string name="settingslib_category_work" msgid="4867750733682444676">"Dienstlich"</string>
- <string name="settingslib_category_private" msgid="5039276873477591386">"Privat"</string>
+ <string name="settingslib_category_private" msgid="5039276873477591386">"Vertraulich"</string>
</resources>
diff --git a/packages/SettingsLib/ProfileSelector/res/values-in/strings.xml b/packages/SettingsLib/ProfileSelector/res/values-in/strings.xml
index 3859f87..c0a4451 100644
--- a/packages/SettingsLib/ProfileSelector/res/values-in/strings.xml
+++ b/packages/SettingsLib/ProfileSelector/res/values-in/strings.xml
@@ -19,5 +19,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="settingslib_category_personal" msgid="1142302328104700620">"Pribadi"</string>
<string name="settingslib_category_work" msgid="4867750733682444676">"Kerja"</string>
- <string name="settingslib_category_private" msgid="5039276873477591386">"Pribadi"</string>
+ <string name="settingslib_category_private" msgid="5039276873477591386">"Privasi"</string>
</resources>
diff --git a/packages/SettingsLib/ProfileSelector/res/values-ka/strings.xml b/packages/SettingsLib/ProfileSelector/res/values-ka/strings.xml
index d6c2e6d..9a86775 100644
--- a/packages/SettingsLib/ProfileSelector/res/values-ka/strings.xml
+++ b/packages/SettingsLib/ProfileSelector/res/values-ka/strings.xml
@@ -19,5 +19,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="settingslib_category_personal" msgid="1142302328104700620">"პირადი"</string>
<string name="settingslib_category_work" msgid="4867750733682444676">"სამსახური"</string>
- <string name="settingslib_category_private" msgid="5039276873477591386">"პირადი"</string>
+ <string name="settingslib_category_private" msgid="5039276873477591386">"კერძო"</string>
</resources>
diff --git a/packages/SettingsLib/ProfileSelector/res/values-ms/strings.xml b/packages/SettingsLib/ProfileSelector/res/values-ms/strings.xml
index e1145c3..2b1f27b 100644
--- a/packages/SettingsLib/ProfileSelector/res/values-ms/strings.xml
+++ b/packages/SettingsLib/ProfileSelector/res/values-ms/strings.xml
@@ -19,5 +19,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="settingslib_category_personal" msgid="1142302328104700620">"Peribadi"</string>
<string name="settingslib_category_work" msgid="4867750733682444676">"Kerja"</string>
- <string name="settingslib_category_private" msgid="5039276873477591386">"Peribadi"</string>
+ <string name="settingslib_category_private" msgid="5039276873477591386">"Persendirian"</string>
</resources>
diff --git a/packages/SettingsLib/ProfileSelector/res/values-pa/strings.xml b/packages/SettingsLib/ProfileSelector/res/values-pa/strings.xml
index 025c1be..e1e68c7 100644
--- a/packages/SettingsLib/ProfileSelector/res/values-pa/strings.xml
+++ b/packages/SettingsLib/ProfileSelector/res/values-pa/strings.xml
@@ -19,5 +19,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="settingslib_category_personal" msgid="1142302328104700620">"ਨਿੱਜੀ"</string>
<string name="settingslib_category_work" msgid="4867750733682444676">"ਕਾਰਜ"</string>
- <string name="settingslib_category_private" msgid="5039276873477591386">"ਨਿੱਜੀ"</string>
+ <string name="settingslib_category_private" msgid="5039276873477591386">"ਪ੍ਰਾਈਵੇਟ"</string>
</resources>
diff --git a/packages/SettingsLib/ProfileSelector/res/values-uk/strings.xml b/packages/SettingsLib/ProfileSelector/res/values-uk/strings.xml
index 76ab328..ca95cdb 100644
--- a/packages/SettingsLib/ProfileSelector/res/values-uk/strings.xml
+++ b/packages/SettingsLib/ProfileSelector/res/values-uk/strings.xml
@@ -17,7 +17,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="settingslib_category_personal" msgid="1142302328104700620">"Особисті"</string>
- <string name="settingslib_category_work" msgid="4867750733682444676">"Робочі"</string>
+ <string name="settingslib_category_personal" msgid="1142302328104700620">"Особистий профіль"</string>
+ <string name="settingslib_category_work" msgid="4867750733682444676">"Робочий профіль"</string>
<string name="settingslib_category_private" msgid="5039276873477591386">"Приватний профіль"</string>
</resources>
diff --git a/packages/SettingsLib/ProfileSelector/res/values-uz/strings.xml b/packages/SettingsLib/ProfileSelector/res/values-uz/strings.xml
index 50ccf1de..6618edd 100644
--- a/packages/SettingsLib/ProfileSelector/res/values-uz/strings.xml
+++ b/packages/SettingsLib/ProfileSelector/res/values-uz/strings.xml
@@ -19,5 +19,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="settingslib_category_personal" msgid="1142302328104700620">"Shaxsiy"</string>
<string name="settingslib_category_work" msgid="4867750733682444676">"Ish"</string>
- <string name="settingslib_category_private" msgid="5039276873477591386">"Yopiq"</string>
+ <string name="settingslib_category_private" msgid="5039276873477591386">"Maxfiy"</string>
</resources>
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/MaterialColors.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/MaterialColors.kt
index 52c4893..d6704a5 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/MaterialColors.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/MaterialColors.kt
@@ -47,3 +47,7 @@
val ColorScheme.surfaceTone: Color
get() = primary.copy(SettingsOpacity.SurfaceTone)
+
+/** The overall background color in Settings. */
+val ColorScheme.settingsBackground: Color
+ get() = surfaceContainer
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/SettingsColors.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/SettingsColors.kt
deleted file mode 100644
index 69aba71..0000000
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/SettingsColors.kt
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settingslib.spa.framework.theme
-
-import android.content.Context
-import android.os.Build
-import androidx.annotation.VisibleForTesting
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.staticCompositionLocalOf
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.platform.LocalContext
-
-data class SettingsColorScheme(
- val background: Color = Color.Unspecified,
- val categoryTitle: Color = Color.Unspecified,
- val surface: Color = Color.Unspecified,
- val surfaceHeader: Color = Color.Unspecified,
- val secondaryText: Color = Color.Unspecified,
- val primaryContainer: Color = Color.Unspecified,
- val onPrimaryContainer: Color = Color.Unspecified,
-)
-
-internal val LocalColorScheme = staticCompositionLocalOf { SettingsColorScheme() }
-
-@Composable
-internal fun settingsColorScheme(isDarkTheme: Boolean): SettingsColorScheme {
- val context = LocalContext.current
- return remember(isDarkTheme) {
- when {
- Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
- if (isDarkTheme) dynamicDarkColorScheme(context)
- else dynamicLightColorScheme(context)
- }
- isDarkTheme -> darkColorScheme()
- else -> lightColorScheme()
- }
- }
-}
-
-/**
- * Creates a light dynamic color scheme.
- *
- * Use this function to create a color scheme based off the system wallpaper. If the developer
- * changes the wallpaper this color scheme will change accordingly. This dynamic scheme is a
- * light theme variant.
- *
- * @param context The context required to get system resource data.
- */
-@VisibleForTesting
-internal fun dynamicLightColorScheme(context: Context): SettingsColorScheme {
- val tonalPalette = dynamicTonalPalette(context)
- return SettingsColorScheme(
- background = tonalPalette.neutral95,
- categoryTitle = tonalPalette.primary40,
- surface = tonalPalette.neutral99,
- surfaceHeader = tonalPalette.neutral90,
- secondaryText = tonalPalette.neutralVariant30,
- primaryContainer = tonalPalette.primary90,
- onPrimaryContainer = tonalPalette.neutral10,
- )
-}
-
-/**
- * Creates a dark dynamic color scheme.
- *
- * Use this function to create a color scheme based off the system wallpaper. If the developer
- * changes the wallpaper this color scheme will change accordingly. This dynamic scheme is a dark
- * theme variant.
- *
- * @param context The context required to get system resource data.
- */
-@VisibleForTesting
-internal fun dynamicDarkColorScheme(context: Context): SettingsColorScheme {
- val tonalPalette = dynamicTonalPalette(context)
- return SettingsColorScheme(
- background = tonalPalette.neutral10,
- categoryTitle = tonalPalette.primary90,
- surface = tonalPalette.neutral20,
- surfaceHeader = tonalPalette.neutral30,
- secondaryText = tonalPalette.neutralVariant80,
- primaryContainer = tonalPalette.secondary90,
- onPrimaryContainer = tonalPalette.neutral10,
- )
-}
-
-@VisibleForTesting
-internal fun darkColorScheme(): SettingsColorScheme {
- val tonalPalette = tonalPalette()
- return SettingsColorScheme(
- background = tonalPalette.neutral10,
- categoryTitle = tonalPalette.primary90,
- surface = tonalPalette.neutral20,
- surfaceHeader = tonalPalette.neutral30,
- secondaryText = tonalPalette.neutralVariant80,
- primaryContainer = tonalPalette.secondary90,
- onPrimaryContainer = tonalPalette.neutral10,
- )
-}
-
-@VisibleForTesting
-internal fun lightColorScheme(): SettingsColorScheme {
- val tonalPalette = tonalPalette()
- return SettingsColorScheme(
- background = tonalPalette.neutral95,
- categoryTitle = tonalPalette.primary40,
- surface = tonalPalette.neutral99,
- surfaceHeader = tonalPalette.neutral90,
- secondaryText = tonalPalette.neutralVariant30,
- primaryContainer = tonalPalette.primary90,
- onPrimaryContainer = tonalPalette.neutral10,
- )
-}
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/SettingsTheme.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/SettingsTheme.kt
index c395558..d9f82e8 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/SettingsTheme.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/SettingsTheme.kt
@@ -21,7 +21,6 @@
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
-import androidx.compose.runtime.ReadOnlyComposable
/**
* The Material 3 Theme for Settings.
@@ -29,24 +28,15 @@
@Composable
fun SettingsTheme(content: @Composable () -> Unit) {
val isDarkTheme = isSystemInDarkTheme()
- val settingsColorScheme = settingsColorScheme(isDarkTheme)
- val colorScheme = materialColorScheme(isDarkTheme).copy(
- background = settingsColorScheme.background,
- )
- MaterialTheme(colorScheme = colorScheme, typography = rememberSettingsTypography()) {
+ MaterialTheme(
+ colorScheme = materialColorScheme(isDarkTheme),
+ typography = rememberSettingsTypography(),
+ ) {
CompositionLocalProvider(
- LocalColorScheme provides settingsColorScheme(isDarkTheme),
LocalContentColor provides MaterialTheme.colorScheme.onSurface,
) {
content()
}
}
}
-
-object SettingsTheme {
- val colorScheme: SettingsColorScheme
- @Composable
- @ReadOnlyComposable
- get() = LocalColorScheme.current
-}
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/button/ActionButtons.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/button/ActionButtons.kt
index 979cf3b..70d353d 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/button/ActionButtons.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/button/ActionButtons.kt
@@ -88,9 +88,9 @@
interactionSource = remember(actionButton) { MutableInteractionSource() },
shape = RectangleShape,
colors = ButtonDefaults.filledTonalButtonColors(
- containerColor = SettingsTheme.colorScheme.surface,
- contentColor = SettingsTheme.colorScheme.categoryTitle,
- disabledContainerColor = SettingsTheme.colorScheme.surface,
+ containerColor = MaterialTheme.colorScheme.surface,
+ contentColor = MaterialTheme.colorScheme.primary,
+ disabledContainerColor = MaterialTheme.colorScheme.surface,
),
contentPadding = PaddingValues(horizontal = 4.dp, vertical = 20.dp),
) {
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/card/SettingsCard.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/card/SettingsCard.kt
index d08d97e..0546719 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/card/SettingsCard.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/card/SettingsCard.kt
@@ -83,7 +83,7 @@
Card(
shape = CornerExtraSmall,
colors = CardDefaults.cardColors(
- containerColor = containerColor.takeOrElse { SettingsTheme.colorScheme.surface },
+ containerColor = containerColor.takeOrElse { MaterialTheme.colorScheme.surface },
),
modifier = Modifier
.fillMaxWidth()
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/CustomizedAppBar.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/CustomizedAppBar.kt
index 56534f4..36cd136 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/CustomizedAppBar.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/CustomizedAppBar.kt
@@ -74,7 +74,7 @@
import androidx.compose.ui.unit.Velocity
import androidx.compose.ui.unit.dp
import com.android.settingslib.spa.framework.theme.SettingsDimension
-import com.android.settingslib.spa.framework.theme.SettingsTheme
+import com.android.settingslib.spa.framework.theme.settingsBackground
import kotlin.math.abs
import kotlin.math.max
import kotlin.math.roundToInt
@@ -140,8 +140,8 @@
@Composable
private fun topAppBarColors() = TopAppBarColors(
- containerColor = MaterialTheme.colorScheme.background,
- scrolledContainerColor = SettingsTheme.colorScheme.surfaceHeader,
+ containerColor = MaterialTheme.colorScheme.settingsBackground,
+ scrolledContainerColor = MaterialTheme.colorScheme.surfaceVariant,
navigationIconContentColor = MaterialTheme.colorScheme.onSurface,
titleContentColor = MaterialTheme.colorScheme.onSurface,
actionIconContentColor = MaterialTheme.colorScheme.onSurfaceVariant,
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/HomeScaffold.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/HomeScaffold.kt
index 711c8a7..feb9737b 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/HomeScaffold.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/HomeScaffold.kt
@@ -28,13 +28,14 @@
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.android.settingslib.spa.framework.theme.SettingsDimension
+import com.android.settingslib.spa.framework.theme.settingsBackground
@Composable
fun HomeScaffold(title: String, content: @Composable () -> Unit) {
Column(
Modifier
.fillMaxSize()
- .background(color = MaterialTheme.colorScheme.background)
+ .background(color = MaterialTheme.colorScheme.settingsBackground)
.systemBarsPadding()
.verticalScroll(rememberScrollState()),
) {
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SearchScaffold.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SearchScaffold.kt
index c87178d..a49b358 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SearchScaffold.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SearchScaffold.kt
@@ -59,6 +59,7 @@
import com.android.settingslib.spa.framework.compose.horizontalValues
import com.android.settingslib.spa.framework.theme.SettingsOpacity
import com.android.settingslib.spa.framework.theme.SettingsTheme
+import com.android.settingslib.spa.framework.theme.settingsBackground
import com.android.settingslib.spa.widget.preference.Preference
import com.android.settingslib.spa.widget.preference.PreferenceModel
@@ -90,6 +91,7 @@
onSearchQueryChange = { viewModel.searchQuery = it },
)
},
+ containerColor = MaterialTheme.colorScheme.settingsBackground,
) { paddingValues ->
Box(
Modifier
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SettingsScaffold.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SettingsScaffold.kt
index 8919402..af7a146 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SettingsScaffold.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SettingsScaffold.kt
@@ -25,6 +25,7 @@
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
@@ -36,6 +37,7 @@
import com.android.settingslib.spa.framework.compose.horizontalValues
import com.android.settingslib.spa.framework.compose.verticalValues
import com.android.settingslib.spa.framework.theme.SettingsTheme
+import com.android.settingslib.spa.framework.theme.settingsBackground
import com.android.settingslib.spa.widget.preference.Preference
import com.android.settingslib.spa.widget.preference.PreferenceModel
@@ -54,6 +56,7 @@
Scaffold(
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
topBar = { SettingsTopAppBar(title, scrollBehavior, actions) },
+ containerColor = MaterialTheme.colorScheme.settingsBackground,
) { paddingValues ->
Box(Modifier.padding(paddingValues.horizontalValues())) {
content(paddingValues.verticalValues())
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SettingsTab.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SettingsTab.kt
index 6f2c38c..60814bf 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SettingsTab.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SettingsTab.kt
@@ -51,8 +51,8 @@
.clip(SettingsShape.CornerMedium)
.background(
color = lerp(
- start = SettingsTheme.colorScheme.primaryContainer,
- stop = SettingsTheme.colorScheme.surface,
+ start = MaterialTheme.colorScheme.primaryContainer,
+ stop = MaterialTheme.colorScheme.surface,
fraction = colorFraction,
),
),
@@ -61,8 +61,8 @@
text = title,
style = MaterialTheme.typography.labelLarge,
color = lerp(
- start = SettingsTheme.colorScheme.onPrimaryContainer,
- stop = SettingsTheme.colorScheme.secondaryText,
+ start = MaterialTheme.colorScheme.onPrimaryContainer,
+ stop = MaterialTheme.colorScheme.onSurface,
fraction = colorFraction,
),
)
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SuwScaffold.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SuwScaffold.kt
index e39b175..fc40930 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SuwScaffold.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SuwScaffold.kt
@@ -37,6 +37,7 @@
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import com.android.settingslib.spa.framework.theme.SettingsDimension
+import com.android.settingslib.spa.framework.theme.settingsBackground
import com.android.settingslib.spa.framework.theme.toMediumWeight
data class BottomAppBarButton(
@@ -54,7 +55,7 @@
content: @Composable () -> Unit,
) {
ActivityTitle(title)
- Scaffold { innerPadding ->
+ Scaffold(containerColor = MaterialTheme.colorScheme.settingsBackground) { innerPadding ->
BoxWithConstraints(
Modifier
.padding(innerPadding)
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Category.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Category.kt
index 6aac5bf3..48cd145 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Category.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Category.kt
@@ -46,7 +46,7 @@
end = SettingsDimension.itemPaddingEnd,
bottom = 8.dp,
),
- color = SettingsTheme.colorScheme.categoryTitle,
+ color = MaterialTheme.colorScheme.primary,
style = MaterialTheme.typography.labelMedium,
)
}
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/CopyableBody.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/CopyableBody.kt
index 930d0a1..99b2524 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/CopyableBody.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/CopyableBody.kt
@@ -37,7 +37,6 @@
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.unit.DpOffset
import com.android.settingslib.spa.framework.theme.SettingsDimension
-import com.android.settingslib.spa.framework.theme.SettingsTheme
@Composable
fun CopyableBody(body: String) {
@@ -78,7 +77,7 @@
top = SettingsDimension.itemPaddingAround,
bottom = SettingsDimension.buttonPaddingVertical,
),
- color = SettingsTheme.colorScheme.categoryTitle,
+ color = MaterialTheme.colorScheme.primary,
style = MaterialTheme.typography.labelMedium,
)
}
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Text.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Text.kt
index d423d9f..6e5f32e 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Text.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Text.kt
@@ -47,7 +47,6 @@
modifier = Modifier
.padding(vertical = SettingsDimension.paddingTiny)
.contentDescription(contentDescription),
- color = MaterialTheme.colorScheme.onSurface,
style = MaterialTheme.typography.titleMedium.withWeight(useMediumWeight),
)
}
diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/theme/SettingsColorsTest.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/theme/SettingsColorsTest.kt
deleted file mode 100644
index 625663d..0000000
--- a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/theme/SettingsColorsTest.kt
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settingslib.spa.framework.theme
-
-import android.content.Context
-import androidx.test.core.app.ApplicationProvider
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import org.junit.runner.RunWith
-import androidx.compose.ui.graphics.Color
-
-@RunWith(AndroidJUnit4::class)
-class SettingsColorsTest {
- private val context: Context = ApplicationProvider.getApplicationContext()
-
- @Test
- fun testDynamicTheme() {
- // The dynamic color could be different in different device, just check basic restrictions:
- // 1. text color is different with background color
- // 2. primary / spinner color is different with its on-item color
- val ls = dynamicLightColorScheme(context)
- assertThat(ls.categoryTitle).isNotEqualTo(ls.background)
- assertThat(ls.secondaryText).isNotEqualTo(ls.background)
- assertThat(ls.primaryContainer).isNotEqualTo(ls.onPrimaryContainer)
-
- val ds = dynamicDarkColorScheme(context)
- assertThat(ds.categoryTitle).isNotEqualTo(ds.background)
- assertThat(ds.secondaryText).isNotEqualTo(ds.background)
- assertThat(ds.primaryContainer).isNotEqualTo(ds.onPrimaryContainer)
- }
-
- @Test
- fun testStaticTheme() {
- val ls = lightColorScheme()
- assertThat(ls.background).isEqualTo(Color(red = 244, green = 239, blue = 244))
- assertThat(ls.categoryTitle).isEqualTo(Color(red = 103, green = 80, blue = 164))
- assertThat(ls.surface).isEqualTo(Color(red = 255, green = 251, blue = 254))
- assertThat(ls.surfaceHeader).isEqualTo(Color(red = 230, green = 225, blue = 229))
- assertThat(ls.secondaryText).isEqualTo(Color(red = 73, green = 69, blue = 79))
- assertThat(ls.primaryContainer).isEqualTo(Color(red = 234, green = 221, blue = 255))
- assertThat(ls.onPrimaryContainer).isEqualTo(Color(red = 28, green = 27, blue = 31))
-
- val ds = darkColorScheme()
- assertThat(ds.background).isEqualTo(Color(red = 28, green = 27, blue = 31))
- assertThat(ds.categoryTitle).isEqualTo(Color(red = 234, green = 221, blue = 255))
- assertThat(ds.surface).isEqualTo(Color(red = 49, green = 48, blue = 51))
- assertThat(ds.surfaceHeader).isEqualTo(Color(red = 72, green = 70, blue = 73))
- assertThat(ds.secondaryText).isEqualTo(Color(red = 202, green = 196, blue = 208))
- assertThat(ds.primaryContainer).isEqualTo(Color(red = 232, green = 222, blue = 248))
- assertThat(ds.onPrimaryContainer).isEqualTo(Color(red = 28, green = 27, blue = 31))
- }
-}
diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/theme/SettingsThemeTest.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/theme/SettingsThemeTest.kt
index bd8a54b..ed7735e 100644
--- a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/theme/SettingsThemeTest.kt
+++ b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/theme/SettingsThemeTest.kt
@@ -26,42 +26,35 @@
import androidx.compose.ui.text.font.FontFamily
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.google.common.truth.Truth.assertThat
-import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
-import org.mockito.Mock
-import org.mockito.junit.MockitoJUnit
-import org.mockito.junit.MockitoRule
import org.mockito.kotlin.any
-import org.mockito.kotlin.whenever
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.stub
@RunWith(AndroidJUnit4::class)
class SettingsThemeTest {
- @get:Rule
- val mockito: MockitoRule = MockitoJUnit.rule()
@get:Rule
val composeTestRule = createComposeRule()
- @Mock
- private lateinit var context: Context
+ private val resources = mock<Resources> {
+ on { getString(any()) } doReturn ""
+ }
- @Mock
- private lateinit var resources: Resources
+ private val context = mock<Context> {
+ on { resources } doReturn resources
+ }
private var nextMockResId = 1
- @Before
- fun setUp() {
- whenever(context.resources).thenReturn(resources)
- whenever(resources.getString(any())).thenReturn("")
- }
-
private fun mockAndroidConfig(configName: String, configValue: String) {
- whenever(resources.getIdentifier(configName, "string", "android"))
- .thenReturn(nextMockResId)
- whenever(resources.getString(nextMockResId)).thenReturn(configValue)
+ resources.stub {
+ on { getIdentifier(configName, "string", "android") } doReturn nextMockResId
+ on { getString(nextMockResId) } doReturn configValue
+ }
nextMockResId++
}
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppList.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppList.kt
index 68da143..bededf0 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppList.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppList.kt
@@ -31,6 +31,7 @@
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.Dp
+import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewmodel.compose.viewModel
import com.android.settingslib.spa.framework.compose.LifecycleEffect
import com.android.settingslib.spa.framework.compose.LogCompositions
@@ -49,7 +50,6 @@
import com.android.settingslib.spaprivileged.model.app.AppRecord
import com.android.settingslib.spaprivileged.model.app.IAppListViewModel
import com.android.settingslib.spaprivileged.model.app.userId
-import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
private const val TAG = "AppList"
@@ -95,9 +95,9 @@
LogCompositions(TAG, config.userIds.toString())
val viewModel = viewModelSupplier()
Column(Modifier.fillMaxSize()) {
- val optionsState = viewModel.spinnerOptionsFlow.collectAsState(null, Dispatchers.IO)
+ val optionsState = viewModel.spinnerOptionsFlow.collectAsStateWithLifecycle(null)
SpinnerOptions(optionsState, viewModel.optionFlow)
- val appListData = viewModel.appListDataFlow.collectAsState(null, Dispatchers.IO)
+ val appListData = viewModel.appListDataFlow.collectAsStateWithLifecycle(null)
listModel.AppListWidget(appListData, header, bottomPadding, noItemMessage)
}
}
diff --git a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/framework/compose/DisposableBroadcastReceiverAsUserTest.kt b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/framework/compose/DisposableBroadcastReceiverAsUserTest.kt
index 5a6c0a1..dd7c036 100644
--- a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/framework/compose/DisposableBroadcastReceiverAsUserTest.kt
+++ b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/framework/compose/DisposableBroadcastReceiverAsUserTest.kt
@@ -27,8 +27,6 @@
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.lifecycle.testing.TestLifecycleOwner
import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.android.settingslib.spa.testutils.delay
-import com.google.common.truth.Truth.assertThat
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -71,9 +69,8 @@
DisposableBroadcastReceiverAsUser(INTENT_FILTER, USER_HANDLE) {}
}
}
- composeTestRule.delay()
- assertThat(registeredBroadcastReceiver).isNotNull()
+ composeTestRule.waitUntil { registeredBroadcastReceiver != null }
}
@Test
@@ -91,9 +88,8 @@
}
registeredBroadcastReceiver!!.onReceive(context, Intent())
- composeTestRule.delay()
- assertThat(onReceiveIsCalled).isTrue()
+ composeTestRule.waitUntil { onReceiveIsCalled }
}
private companion object {
diff --git a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalBooleanTest.kt b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalBooleanTest.kt
index 70b38fe..cd747cc1 100644
--- a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalBooleanTest.kt
+++ b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalBooleanTest.kt
@@ -102,7 +102,8 @@
delay(100)
value = true
- assertThat(listDeferred.await()).containsExactly(false, true).inOrder()
+ assertThat(listDeferred.await())
+ .containsAtLeast(false, true).inOrder()
}
private companion object {
diff --git a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsSecureBooleanTest.kt b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsSecureBooleanTest.kt
index 29a89be..ecc92f8 100644
--- a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsSecureBooleanTest.kt
+++ b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsSecureBooleanTest.kt
@@ -102,7 +102,8 @@
delay(100)
value = true
- assertThat(listDeferred.await()).containsExactly(false, true).inOrder()
+ assertThat(listDeferred.await())
+ .containsAtLeast(false, true).inOrder()
}
private companion object {
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 9641204..1594e8e 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -96,10 +96,8 @@
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Gekoppel (geen foon of media nie), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Aktief. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
<string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Aktief. L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery."</string>
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Aktief. L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Aktief. R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batterykrag"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery."</string>
@@ -107,12 +105,9 @@
<string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Regs: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktief"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Gestoor"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Aktief (net linkerkant)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Aktief (net regterkant)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Aktief (linkerkant en regterkant)"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktief (net media). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktiewe (net media). L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery"</string>
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Gekoppel (steun oudiodeling). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string>
@@ -290,9 +285,9 @@
<string name="oem_unlock_enable_summary" msgid="5857388174390953829">"Laat toe dat die selflaaiprogram ontsluit word"</string>
<string name="confirm_enable_oem_unlock_title" msgid="8249318129774367535">"Laat OEM-ontsluit toe?"</string>
<string name="confirm_enable_oem_unlock_text" msgid="854131050791011970">"WAARSKUWING: Toestelbeskermingkenmerke sal nie op hierdie toestel werk terwyl hierdie instelling aangeskakel is nie."</string>
- <string name="mock_location_app" msgid="6269380172542248304">"Kies skynliggingprogram"</string>
+ <string name="mock_location_app" msgid="6269380172542248304">"Kies skynliggingapp"</string>
<string name="mock_location_app_not_set" msgid="6972032787262831155">"Geen skynliggingprogram gestel nie"</string>
- <string name="mock_location_app_set" msgid="4706722469342913843">"Skynliggingprogram: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="mock_location_app_set" msgid="4706722469342913843">"Skynliggingapp: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="debug_networking_category" msgid="6829757985772659599">"Inligtingruiling"</string>
<string name="wifi_display_certification" msgid="1805579519992520381">"Draadlose skermsertifisering"</string>
<string name="wifi_verbose_logging" msgid="1785910450009679371">"Aktiveer Wi-Fi-woordryke aanmelding"</string>
@@ -376,7 +371,7 @@
<string name="media_category" msgid="8122076702526144053">"Media"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Monitering"</string>
<string name="strict_mode" msgid="889864762140862437">"Strengmodus geaktiveer"</string>
- <string name="strict_mode_summary" msgid="1838248687233554654">"Flits skerm as programme lang bewerkings uitvoer op die hoofdraad"</string>
+ <string name="strict_mode_summary" msgid="1838248687233554654">"Flits skerm as apps lang bewerkings uitvoer op die hoofdraad"</string>
<string name="pointer_location" msgid="7516929526199520173">"Wyserligging"</string>
<string name="pointer_location_summary" msgid="957120116989798464">"Skermlaag wys huidige raakdata"</string>
<string name="show_touches" msgid="8437666942161289025">"Wys tikke"</string>
@@ -450,7 +445,7 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Onaktief. Tik om te wissel."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktief. Tik om te wissel."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Programbystandstatus:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="2581975870429850549">"Mediakodewisselinginstellings"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Mediatranskoderinginstellings"</string>
<string name="transcode_user_control" msgid="6176368544817731314">"Ignoreer kodewisselingverstekke"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Aktiveer kodewisseling"</string>
<string name="transcode_default" msgid="3784803084573509491">"Aanvaar dat programme moderne formate steun"</string>
@@ -726,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Neutrum"</string>
<string name="feminine" msgid="1529155595310784757">"Vroulik"</string>
<string name="masculine" msgid="4653978041013996303">"Manlik"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Stelselopdaterings"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 51cf441..b65fdc0 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"ተገናኝቷል (ምንም ስልክ የለም)፣ ባትሪ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"ተገናኝቷል (ምንም ማህደረ መረጃ የለም)፣ ባትሪ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"ተገናኝቷል (ምንም ስልክ ወይም ማህደረ መረጃ የለም)፣ ባትሪ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"ገቢር። <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ባትሪ።"</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"ገቢር። ግ፦ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>፣ ቀ፦ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ባትሪ።"</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"ገቢር። ግ፦ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ባትሪ።"</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"ገቢር። ቀ፦ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ባትሪ።"</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ባትሪ"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"ባትሪ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"ግ፦ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>፣ ቀ፦ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ባትሪ።"</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"ግራ፦ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ባትሪ"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"ቀኝ፦ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ባትሪ"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"ንቁ"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"ተቀምጧል"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"ገቢር (ግራ ብቻ)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"ገቢር (ቀኝ ብቻ)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"ገቢር (ግራ እና ቀኝ)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"ገቢር (ሚዲያ ብቻ)። <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ባትሪ።"</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"ገቢር (ሚዲያ ብቻ)። ግ፦ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>፣ ቀ፦ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ባትሪ።"</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"ተገናኝቷል (የድምፅ ማጋራት ይደግፋል)፣ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ባትሪ።"</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"ተገናኝቷል (የድምፅ ማጋራት ይደግፋል) ግ፦ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>፣ ቀ፦ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ባትሪ።"</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"ተገናኝቷል (የድምፅ ማጋራት ይደግፋል)። ግራ፦<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ባትሪ።"</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"ተገናኝቷል (የድምፅ ማጋራት ይደግፋል)። ቀኝ፦ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ባትሪ።"</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"ተገናኝቷል (የድምፅ ማጋራት ይደግፋል)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"ገቢር (ሚዲያ ብቻ)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"ድምፅ ማጋራትን ይደግፋል"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"ገቢር (ሚዲያ ብቻ)፣ ግራ ብቻ"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"ገለልተኛ"</string>
<string name="feminine" msgid="1529155595310784757">"እንስት"</string>
<string name="masculine" msgid="4653978041013996303">"ተባዕታይ"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"የሥርዓት ዝማኔዎች"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 4b1e925..cfa5b14 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -96,10 +96,8 @@
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"متّصل (بدون هاتف أو وسائط)، ومستوى البطارية <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_active_battery_level" msgid="2685517576209066008">"البلوتوث نشِط. مستوى شحن البطارية: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"البلوتوث نشِط. مستوى الشحن في سماعة الرأس اليسرى: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>، مستوى الشحن في سماعة الرأس اليمنى: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"البلوتوث نشِط. مستوى الشحن في سماعة الرأس اليسرى: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"البلوتوث نشِط. مستوى الشحن في سماعة الرأس اليمنى: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"مستوى طاقة البطارية <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"مستوى شحن البطارية: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"مستوى الشحن في سماعة الرأس اليسرى: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>، مستوى الشحن في سماعة الرأس اليمنى: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
@@ -107,12 +105,9 @@
<string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"مستوى الشحن في سماعة الرأس اليمنى: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"نشط"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"محفوظ"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"سماعة الأذن الطبية نشطة (اليسرى فقط)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"سماعة الأذن الطبية نشطة (اليمنى فقط)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"سماعتا الأذن الطبيتان نشطتان (اليسرى واليمنى)"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"البلوتوث نشِط (للوسائط فقط). مستوى شحن البطارية: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"البلوتوث نشِط (للوسائط فقط)، مستوى الشحن في سماعة الرأس اليسرى: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>، مستوى الشحن في سماعة الرأس اليمنى: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"البلوتوث متصل (ميزة \"مشاركة الصوت\" متاحة). مستوى شحن البطارية: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -199,7 +194,7 @@
<string name="launch_defaults_some" msgid="3631650616557252926">"تم ضبط بعض الإعدادات التلقائية"</string>
<string name="launch_defaults_none" msgid="8049374306261262709">"لم يتم ضبط إعدادات تلقائية"</string>
<string name="tts_settings" msgid="8130616705989351312">"إعدادات تحويل النص إلى كلام"</string>
- <string name="tts_settings_title" msgid="7602210956640483039">"الصوت عند تحويل النص إلى كلام"</string>
+ <string name="tts_settings_title" msgid="7602210956640483039">"الرد الصوتي"</string>
<string name="tts_default_rate_title" msgid="3964187817364304022">"سرعة الكلام"</string>
<string name="tts_default_rate_summary" msgid="3781937042151716987">"سرعة قول الكلام"</string>
<string name="tts_default_pitch_title" msgid="6988592215554485479">"درجة الصوت"</string>
@@ -213,7 +208,7 @@
<string name="tts_install_data_title" msgid="1829942496472751703">"تثبيت البيانات الصوتية"</string>
<string name="tts_install_data_summary" msgid="3608874324992243851">"تثبيت البيانات الصوتية المطلوبة لتجميع الكلام"</string>
<string name="tts_engine_security_warning" msgid="3372432853837988146">"ربما يمكن لمحرك اصطناع الحديث جمع كل النص التي سيتم نطقه، بما في ذلك البيانات الشخصية مثل كلمات المرور وأرقام بطاقة الائتمان. يتم إحضار ذلك من المحرك <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>. هل تريد تفعيل استخدام محرك اصطناع الحديث هذا؟"</string>
- <string name="tts_engine_network_required" msgid="8722087649733906851">"تتطلب هذه اللغة اتصال شبكة سليمًا لتحويل النص إلى كلام."</string>
+ <string name="tts_engine_network_required" msgid="8722087649733906851">"تتطلب هذه اللغة اتصال شبكة سليمًا لاستخدام ميزة الرد الصوتي."</string>
<string name="tts_default_sample_string" msgid="6388016028292967973">"هذا مثال لتركيب الكلام"</string>
<string name="tts_status_title" msgid="8190784181389278640">"حالة اللغة التلقائية"</string>
<string name="tts_status_ok" msgid="8583076006537547379">"<xliff:g id="LOCALE">%1$s</xliff:g> متوافقة تمامًا"</string>
@@ -237,10 +232,10 @@
<item msgid="4446831566506165093">"350%"</item>
<item msgid="6946761421234586000">"400%"</item>
</string-array>
- <string name="choose_profile" msgid="343803890897657450">"اختيار ملف شخصي"</string>
- <string name="category_personal" msgid="6236798763159385225">"الحسابات الشخصية"</string>
- <string name="category_work" msgid="4014193632325996115">"حسابات العمل"</string>
- <string name="category_private" msgid="4244892185452788977">"ملف شخصي"</string>
+ <string name="choose_profile" msgid="343803890897657450">"تحديد الملف"</string>
+ <string name="category_personal" msgid="6236798763159385225">"الملف الشخصي"</string>
+ <string name="category_work" msgid="4014193632325996115">"ملف العمل"</string>
+ <string name="category_private" msgid="4244892185452788977">"الملف الخاص"</string>
<string name="category_clone" msgid="1554511758987195974">"استنساخ"</string>
<string name="development_settings_title" msgid="140296922921597393">"خيارات المطورين"</string>
<string name="development_settings_enable" msgid="4285094651288242183">"تفعيل خيارات المطورين"</string>
@@ -726,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"صيغة مخاطبة محايدة"</string>
<string name="feminine" msgid="1529155595310784757">"صيغة مخاطبة مؤنثة"</string>
<string name="masculine" msgid="4653978041013996303">"صيغة مخاطبة مذكّرة"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"تحديثات النظام"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index 13b639a..debef2c 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"সংযোগ কৰা হ’ল (ফ\'ন নাই), বেটাৰীৰ স্তৰ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"সংযোগ কৰা হ’ল (মিডিয়া নাই), বেটাৰীৰ স্তৰ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"সংযোগ কৰা হ’ল (কোনো ফ\'ন বা মিডিয়া নাই), বেটাৰীৰ স্তৰ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"সক্ৰিয় হৈ আছে। <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> বেটাৰী।"</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"সক্ৰিয় হৈ আছে। বাওঁ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, সোঁ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> বেটাৰী।"</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"সক্ৰিয় হৈ আছে। বাওঁ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> বেটাৰী।"</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"সক্ৰিয় হৈ আছে। সোঁ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> বেটাৰী।"</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> বেটাৰী"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"বেটাৰী <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"বাওঁ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, সোঁ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> বেটাৰী।"</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"বাকী আছে: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> বেটাৰী"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"সোঁ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> বেটাৰী"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"সক্ৰিয়"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"ছেভ কৰা হৈছে"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"সক্ৰিয় হৈ আছে (কেৱল বাওঁফালৰটো)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"সক্ৰিয় হৈ আছে (কেৱল সোঁফালৰটো)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"সক্ৰিয় হৈ আছে (বাওঁফালৰটো আৰু সোঁফালৰটো)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"সক্ৰিয় হৈ আছে (কেৱল মিডিয়া)। <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> বেটাৰী।"</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"সক্ৰিয় হৈ আছে (কেৱল মিডিয়া)। বাওঁ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, সোঁ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> বেটাৰী।"</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"সংযুক্ত হৈ আছে (অডিঅ’ শ্বেয়াৰিং সমৰ্থন কৰে), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> বেটাৰী।"</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"সংযুক্ত হৈ আছে (অডিঅ’ শ্বেয়াৰিং সমৰ্থন কৰে), বাওঁ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, সোঁ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> বেটাৰী"</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"সংযুক্ত হৈ আছে (অডিঅ’ শ্বেয়াৰিং সমৰ্থন কৰে)। বাকী আছে: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> বেটাৰী।"</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"সংযুক্ত হৈ আছে (অডিঅ’ শ্বেয়াৰিং সমৰ্থন কৰে)। সোঁ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> বেটাৰী।"</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"সংযুক্ত হৈ আছে (অডিঅ’ শ্বেয়াৰিং সমৰ্থন কৰে)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"সক্ৰিয় হৈ আছে (কেৱল মিডিয়া)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"অডিঅ’ শ্বেয়াৰিং সমৰ্থন কৰে"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"সক্ৰিয় হৈ আছে (কেৱল মিডিয়া), কেৱল বাওঁ"</string>
@@ -388,7 +371,7 @@
<string name="media_category" msgid="8122076702526144053">"মিডিয়া"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"নিৰীক্ষণ কৰি থকা হৈছে"</string>
<string name="strict_mode" msgid="889864762140862437">"কঠোৰ ম’ড সক্ষম কৰা হৈছে"</string>
- <string name="strict_mode_summary" msgid="1838248687233554654">"যেতিয়া এপ্সমূহে মুখ্য থ্ৰেডত দীঘলীয়া কাৰ্যকলাপ চলাই, তেতিয়া স্ক্ৰীন ফ্লাশ্ব কৰক"</string>
+ <string name="strict_mode_summary" msgid="1838248687233554654">"যেতিয়া এপ্সমূহে মুখ্য থ্ৰেডত দীঘলীয়া কাৰ্যকলাপ চলায়, তেতিয়া স্ক্ৰীন ফ্লাশ্ব কৰক"</string>
<string name="pointer_location" msgid="7516929526199520173">"পইণ্টাৰৰ অৱস্থান"</string>
<string name="pointer_location_summary" msgid="957120116989798464">"চলিত স্পৰ্শ-বিষয়ক তথ্যসহ স্ক্ৰীন অভাৰলে’"</string>
<string name="show_touches" msgid="8437666942161289025">"টেপসমূহ দেখুৱাওক"</string>
@@ -429,7 +412,7 @@
<string name="overlay_display_devices_title" msgid="5411894622334469607">"গৌণ প্ৰদৰ্শনৰ নকল বনাওক"</string>
<string name="debug_applications_category" msgid="5394089406638954196">"এপ্সমূহ"</string>
<string name="immediately_destroy_activities" msgid="1826287490705167403">"কাৰ্যকলাপসমূহ নাৰাখিব"</string>
- <string name="immediately_destroy_activities_summary" msgid="6289590341144557614">"ব্যৱহাৰকাৰী ওলোৱাৰ লগে লগে সকলো কাৰ্যকলাপ মচক"</string>
+ <string name="immediately_destroy_activities_summary" msgid="6289590341144557614">"ব্যৱহাৰকাৰী ওলোৱাৰ লগে লগে আটাইবোৰ কাৰ্যকলাপ মচক"</string>
<string name="app_process_limit_title" msgid="8361367869453043007">"নেপথ্যত চলা প্ৰক্ৰিয়াৰ সীমা"</string>
<string name="show_all_anrs" msgid="9160563836616468726">"নেপথ্য এএনআৰবোৰ দেখুৱাওক"</string>
<string name="show_all_anrs_summary" msgid="8562788834431971392">"নেপথ্য এপসমূহৰ বাবে এপে সঁহাৰি দিয়া নাই ডায়ল\'গ প্ৰদৰ্শন কৰক"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"ক্লীৱ লিংগ"</string>
<string name="feminine" msgid="1529155595310784757">"নাৰী-বিষয়ক"</string>
<string name="masculine" msgid="4653978041013996303">"পুৰুষ-বিষয়ক"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"ছিষ্টেম আপডে’ট"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index a3c0aac..9541a98 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -96,10 +96,8 @@
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Qoşuludur (telefon və ya media yoxdur), batareya <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Aktiv. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batareya."</string>
<string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Aktiv. Sol: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Sağ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batareya."</string>
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Aktiv. Sol: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batareya."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Aktiv. Sağ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batareya."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batareya"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Batareya: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"Sol: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Sağ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batareya."</string>
@@ -107,12 +105,9 @@
<string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Sağ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batareya"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktiv"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Yadda saxlandı"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Aktiv (yalnız sol)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Aktiv (yalnız sağ)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Aktiv (sol və sağ)"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktiv (yalnız media). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batareya."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktiv (yalnız media). Sol: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Sağ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batareya."</string>
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Qoşulub (audio paylaşma dəstəklənir). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batareya."</string>
@@ -240,7 +235,7 @@
<string name="choose_profile" msgid="343803890897657450">"Profil seçin"</string>
<string name="category_personal" msgid="6236798763159385225">"Şəxsi"</string>
<string name="category_work" msgid="4014193632325996115">"İş"</string>
- <string name="category_private" msgid="4244892185452788977">"Şəxsi"</string>
+ <string name="category_private" msgid="4244892185452788977">"Məxfi"</string>
<string name="category_clone" msgid="1554511758987195974">"Klonlayın"</string>
<string name="development_settings_title" msgid="140296922921597393">"Developer seçimləri"</string>
<string name="development_settings_enable" msgid="4285094651288242183">"Developer variantlarını aktiv edin"</string>
@@ -726,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Neytral"</string>
<string name="feminine" msgid="1529155595310784757">"Qadın"</string>
<string name="masculine" msgid="4653978041013996303">"Kişi"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Sistem güncəllənmələri"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 24830b4..eda08fb0 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Povezano (bez telefona), nivo baterije je <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Povezano (bez medija), nivo baterije je <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Povezano (bez telefona ili medija), nivo baterije je <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Aktivno. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Aktivno. Levo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, desno: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> baterije."</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Aktivno. Levo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Aktivno. Desno: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Nivo baterije je <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Baterija, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"Levo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, desno: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> baterije."</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"Levo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Desno: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktivan"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Sačuvano"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Aktivno (samo levo)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Aktivno (samo desno)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Aktivno (levo i desno)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktivno (samo za medije). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije."</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktivno (samo za medije). Levo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, desno: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> baterije."</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Povezano (podržava deljenje zvuka), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije."</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Povezano (podržava deljenje zvuka), levo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, desno: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> baterije."</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Povezano (podržava deljenje zvuka). Levo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije"</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Povezano (podržava deljenje zvuka). Desno: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije."</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Povezano (podržava deljenje zvuka)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktivan (samo za medije)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Podržava deljenje zvuka"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktivan (samo za medije), samo levo"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Srednji rod"</string>
<string name="feminine" msgid="1529155595310784757">"Ženski rod"</string>
<string name="masculine" msgid="4653978041013996303">"Muški rod"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Ažuriranja sistema."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 986c089..1c6705e 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Падключана прылада <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (без званкоў). Узровень зараду яе акумулятара: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Падключана прылада <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (без аўдыя). Узровень зараду яе акумулятара: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Падключана прылада <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (без званкоў і аўдыя). Узровень зараду яе акумулятара: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Выкарыстоўваецца. Зарад акумулятара: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Выкарыстоўваецца. Зарад акумулятара: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> (левы навушнік), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> (правы навушнік)."</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Выкарыстоўваецца. Зарад акумулятара левага навушніка: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Выкарыстоўваецца. Зарад акумулятара правага навушніка: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Узровень зараду: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Зарад акумулятара: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"Зарад акумулятара: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> (левы навушнік), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> (правы навушнік)."</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"Зарад акумулятара: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> (левы навушнік)"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Зарад акумулятара: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> (правы навушнік)"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Уключана"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Захавана"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Выкарыстоўваецца (толькі левы навушнік)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Выкарыстоўваецца (толькі правы навушнік)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Выкарыстоўваецца (левы і правы навушнікі)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Выкарыстоўваецца (толькі для мультымедыя). Зарад акумулятара: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Выкарыстоўваецца (толькі для мультымедыя). Зарад акумулятара: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> (левы навушнік), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> (правы навушнік)."</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Падключана (падтрымліваецца абагульванне аўдыя). Зарад акумулятара: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Падключана (падтрымліваецца абагульванне аўдыя). Зарад акумулятара: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> (левы навушнік), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> (правы навушнік)."</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Падключана (падтрымліваецца абагульванне аўдыя). Зарад акумулятара: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> (левы навушнік)."</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Падключана (падтрымліваецца абагульванне аўдыя). Зарад акумулятара: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> (правы навушнік)."</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Падключана (падтрымліваецца абагульванне аўдыя)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Выкарыстоўваецца (толькі для мультымедыя)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Падтрымліваецца абагульванне аўдыя"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Выкарыстоўваецца (толькі для мультымедыя), толькі левы навушнік"</string>
@@ -252,7 +235,7 @@
<string name="choose_profile" msgid="343803890897657450">"Выбраць профіль"</string>
<string name="category_personal" msgid="6236798763159385225">"Асабісты"</string>
<string name="category_work" msgid="4014193632325996115">"Працоўны"</string>
- <string name="category_private" msgid="4244892185452788977">"Прыватныя"</string>
+ <string name="category_private" msgid="4244892185452788977">"Прыватны"</string>
<string name="category_clone" msgid="1554511758987195974">"Клон"</string>
<string name="development_settings_title" msgid="140296922921597393">"Параметры распрацоўшчыка"</string>
<string name="development_settings_enable" msgid="4285094651288242183">"Уключыць параметры распрацоўшчыка"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Ніякі"</string>
<string name="feminine" msgid="1529155595310784757">"Жаночы"</string>
<string name="masculine" msgid="4653978041013996303">"Мужчынскі"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Абнаўленні сістэмы"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 7097078..d6794a2 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Свързано (без телефон), батерия: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Свързано (без мултимедия), батерия: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Свързано (без телефон или мултимедия), батерия: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Активно. Батерия – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Активно. Л: батерия – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Д: батерия – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Активно. Л: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батерия."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Активно. Д: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батерия."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Батерия: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Батерия: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"Л: батерия – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Д: батерия – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"За ляво ухо. Батерия: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"За дясно ухо. Батерия: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Активно"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Запазено"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Активно (само лявото)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Активно (само дясното)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Активно (лявото и дясното)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Активно (само за мултимедия). Батерия – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Активно (само за мултимедия). Л: батерия – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Д: батерия – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Свързано (поддържа споделяне на звука). Батерия – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Свързано (поддържа споделяне на звука). Л: батерия – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Д: батерия – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Свързано (поддържа споделяне на звука). За ляво ухо. Батерия: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Свързано (поддържа споделяне на звука). За дясно ухо. Батерия: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Свързано (поддържа споделяне на звука)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Активно (само за мултимедия)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Поддържа споделяне на звука"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Активно (само за мултимедия), само лявата"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Среден род"</string>
<string name="feminine" msgid="1529155595310784757">"Женски род"</string>
<string name="masculine" msgid="4653978041013996303">"Мъжки род"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Системни актуализации"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index e4637fe..57bc401 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"কানেক্ট করা আছে (ফোনের অডিও ছাড়া), ব্যাটারি <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"কানেক্ট করা আছে (মিডিয়ার অডিও ছাড়া), ব্যাটারি <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"কানেক্ট করা আছে (ফোনের বা মিডিয়ার অডিও ছাড়া), ব্যাটারি <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"চালু আছে। <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ব্যাটারি।"</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"চালু আছে। বাঁদিক: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, ডানদিক: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ব্যাটারি।"</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"চালু আছে। বাঁদিক: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ব্যাটারি।"</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"চালু আছে। ডানদিক: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ব্যাটারি।"</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"চার্জ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"ব্যাটারি <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"বাঁদিক: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, ডানদিক: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ব্যাটারি।"</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"বাঁদিক: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ব্যাটারি"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"ডানদিক: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ব্যাটারি"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"চালু আছে"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"সেভ করা আছে"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"চালু আছে (শুধু বাঁদিক)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"চালু আছে (শুধু ডানদিক)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"চালু আছে (বাঁদিক ও ডানদিক)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"চালু আছে (শুধুমাত্র মিডিয়া)। <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ব্যাটারি।"</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"চালু আছে (শুধুমাত্র মিডিয়া), বাঁদিক: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, ডানদিক: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ব্যাটারি।"</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"কানেক্ট করা আছে (অডিও শেয়ারিংয়ে কাজ করে), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ব্যাটারি।"</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"কানেক্ট করা আছে (অডিও শেয়ারিংয়ে কাজ করে), বাঁদিক: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, ডানদিক: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ব্যাটারি।"</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"কানেক্ট করা আছে (অডিও শেয়ারিংয়ে কাজ করে)। বাঁদিক: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ব্যাটারি।"</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"কানেক্ট করা আছে (অডিও শেয়ারিংয়ে কাজ করে)। ডানদিকে: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ব্যাটারি।"</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"কানেক্ট করা আছে (অডিও শেয়ারিংয়ে কাজ করে)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"চালু আছে (শুধুমাত্র মিডিয়া)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"অডিও শেয়ারিংয়ে কাজ করে"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"চালু আছে (শুধুমাত্র মিডিয়া), শুধুমাত্র বাঁদিক"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"ক্লীব"</string>
<string name="feminine" msgid="1529155595310784757">"স্ত্রী"</string>
<string name="masculine" msgid="4653978041013996303">"পুং"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"সিস্টেম আপডেট"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index e71c2ec..9d914db 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Povezano (bez telefona), baterija <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Povezano (bez medija), baterija <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Povezano (bez telefona ili medija), baterija <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Aktivno. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Aktivno. L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> baterije, D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> baterije."</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Aktivno. L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Aktivno. D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Baterija <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> baterije, D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> baterije."</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"Lijevo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Desno: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktivan"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Sačuvano"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Aktivno (samo lijevo)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Aktivno (samo desno)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Aktivno (lijevo i desno)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktivno (samo za medijski sadržaj). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije."</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktivno (samo za medijski sadržaj). L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> baterije, D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> baterije."</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Povezano (podržava dijeljenje zvuka). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije."</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Povezano (podržava dijeljenje zvuka). L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> baterije, D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> baterije."</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Povezano (podržava dijeljenje zvuka). Lijevo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije."</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Povezano (podržava dijeljenje zvuka). Desno: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije."</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Povezano (podržava dijeljenje zvuka)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktivno (samo za medijski sadržaj)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Podržava dijeljenje zvuka"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktivno (samo za medijski sadržaj), samo lijevo"</string>
@@ -418,7 +401,7 @@
<string name="force_msaa" msgid="4081288296137775550">"Prinudno primijeni 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"Omogućava 4x MSAA u OpenGL ES 2.0 aplikacijama"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"Otkl. greške na operac. nepravoug. isjecanja"</string>
- <string name="track_frame_time" msgid="522674651937771106">"Profil HWUI iscrtavanja"</string>
+ <string name="track_frame_time" msgid="522674651937771106">"Iscrtavanje pomoću HWUI-a"</string>
<string name="enable_gpu_debug_layers" msgid="4986675516188740397">"Omogući slojeve za otklanjanje grešaka na GPU-u"</string>
<string name="enable_gpu_debug_layers_summary" msgid="4921521407377170481">"Omogućite slojeve za otkl. grešaka na GPU-u za apl. za otkl. grešaka"</string>
<string name="enable_verbose_vendor_logging" msgid="1196698788267682072">"Omogući opširni zapisnik"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Srednji rod"</string>
<string name="feminine" msgid="1529155595310784757">"Ženski rod"</string>
<string name="masculine" msgid="4653978041013996303">"Muški rod"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Ažuriranja sistema"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 09b4297..eb7bd7b 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> connectat (sense accés al telèfon), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> connectat (sense accés al contingut multimèdia), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> connectat (sense accés al telèfon ni al contingut multimèdia), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Actiu. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Actiu. E: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de bateria, D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de bateria."</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Actiu. E: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Actiu. D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"E: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de bateria, D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de bateria."</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"Esquerre: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Dret: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria."</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Actiu"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Desat"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Actiu (només l\'esquerre)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Actiu (només el dret)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Actiu (esquerre i dret)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Actiu (només contingut multimèdia). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria."</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Actiu (només contingut multimèdia), E: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de bateria, D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de bateria."</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Connectat (admet compartició d\'àudio). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria."</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Connectat (admet compartició d\'àudio), E: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de bateria, D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de bateria."</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Connectat (admet compartició d\'àudio). Esquerre: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria."</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Connectat (admet compartició d\'àudio). Dret: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria."</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Connectat (admet compartició d\'àudio)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Actiu (només contingut multimèdia)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Admet compartició d\'àudio"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Actiu (només contingut multimèdia), només esquerre"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Neutre"</string>
<string name="feminine" msgid="1529155595310784757">"Femení"</string>
<string name="masculine" msgid="4653978041013996303">"Masculí"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Actualitzacions del sistema"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index b2d75bd..6fa6e12 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Připojeno k zařízení <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (bez telefonu), úroveň baterie <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Připojeno k zařízení <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (bez médií), úroveň baterie <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Připojeno k zařízení <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (bez telefonu a médií), úroveň baterie <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Aktivní. Baterie: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Aktivní. Baterie: L <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, P <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Aktivní. L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterie"</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Aktivní. P: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterie"</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterie"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Baterie <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"Baterie: L <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, P <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"Levá strana: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterie"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Pravá strana: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterie"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktivní"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Uloženo"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Aktivní (pouze levé)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Aktivní (pouze pravé)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Aktivní (levé a pravé)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktivní (pouze média). Baterie: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktivní (pouze média), baterie: L <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, P <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Připojeno (podporuje sdílení zvuku), baterie: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Připojeno (podporuje sdílení zvuku), baterie: L <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, P <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Připojeno (podporuje sdílení zvuku). Levá strana: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterie"</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Připojeno (podporuje sdílení zvuku). Pravá strana: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterie."</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Připojeno (podporuje sdílení zvuku)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktivní (pouze média)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Podporuje sdílení zvuku"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktivní (pouze média), pouze levé"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Střední rod"</string>
<string name="feminine" msgid="1529155595310784757">"Ženský rod"</string>
<string name="masculine" msgid="4653978041013996303">"Mužský rod"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Aktualizace systému"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 0f92316..fc2191c 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Forbundet med <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (ingen telefon) – batteriniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Forbundet med <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (ingen medier) – batteriniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Forbundet med <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (ingen telefon eller medier) – batteriniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Aktiveret. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Aktiveret. V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, H: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batteri."</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Aktiveret. V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Aktiveret. H: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Batteri: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, H: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batteri."</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"Venstre: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Højre: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktiv"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Gemt"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Aktiveret (kun venstre)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Aktiveret (kun højre)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Aktiveret (venstre og højre)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktiveret (kun for medier). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri."</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktiveret (kun for medier), V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, H: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batteri."</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Forbundet (understøtter lyddeling). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri."</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Forbundet (understøtter lyddeling), V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, H: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batteri."</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Forbundet (understøtter lyddeling). Venstre: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri."</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Forbundet (understøtter lyddeling). Højre: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri."</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Forbundet (understøtter lyddeling)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktiveret (kun for medier)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Understøtter lyddeling"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktiveret (kun for medier), kun venstre"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Neutrum"</string>
<string name="feminine" msgid="1529155595310784757">"Femininum"</string>
<string name="masculine" msgid="4653978041013996303">"Maskulinum"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Systemopdateringer"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index c8d7acd..793560d 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Mit <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> verbunden (kein Telefon-Audio), Akkustand bei <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Mit <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> verbunden (kein Medien-Audio), Akkustand bei <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Mit <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> verbunden (weder Telefon- noch Medien-Audio), Akkustand bei <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Aktiv. Akku: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Aktiv. Akku links: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Akku rechts: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Aktiv. L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> Akku."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Aktiv. R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> Akku."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Akkustand: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Akku – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"Akku links: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Akku rechts: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"Akku links: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Akku rechts: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktiv"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Gespeichert"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Aktiv (nur links)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Aktiv (nur rechts)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Aktiv (links und rechts)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktiv (nur Medien). Akku: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktiv (nur Medien). Akku links: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Akku rechts: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Verbunden (unterstützt Audiofreigabe). Akku: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Verbunden (unterstützt Audiofreigabe). Akku links: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Akku rechts: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Verbunden (unterstützt Audiofreigabe). Akku links: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Verbunden (unterstützt Audiofreigabe). Akku rechts: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Verbunden (unterstützt Audiofreigabe)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktiv (nur Medien)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Unterstützt Audiofreigabe"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktiv (nur Medien), nur links"</string>
@@ -252,7 +235,7 @@
<string name="choose_profile" msgid="343803890897657450">"Profil auswählen"</string>
<string name="category_personal" msgid="6236798763159385225">"Privat"</string>
<string name="category_work" msgid="4014193632325996115">"Geschäftlich"</string>
- <string name="category_private" msgid="4244892185452788977">"Privat"</string>
+ <string name="category_private" msgid="4244892185452788977">"Vertraulich"</string>
<string name="category_clone" msgid="1554511758987195974">"Klonen"</string>
<string name="development_settings_title" msgid="140296922921597393">"Entwickleroptionen"</string>
<string name="development_settings_enable" msgid="4285094651288242183">"Entwickleroptionen aktivieren"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Neutrum"</string>
<string name="feminine" msgid="1529155595310784757">"Feminin"</string>
<string name="masculine" msgid="4653978041013996303">"Maskulin"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Systemupdates"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index 2cc9350..6bcdc81 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Σε σύνδεση (χωρίς τηλέφωνο), μπαταρία <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Σε σύνδεση (χωρίς μέσα), μπαταρία <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Σε σύνδεση (χωρίς τηλέφωνο ή μέσα), μπαταρία <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Ενεργό. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> μπαταρία."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Ενεργό. Α: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Δ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> μπαταρία."</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Ενεργό. Α: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> μπαταρία."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Ενεργό. Δ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> μπαταρία."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> μπαταρία"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Μπαταρία <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"Α: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Δ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> μπαταρία."</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"Αριστερά: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> μπαταρία"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Δεξιά: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> μπαταρία"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Ενεργό"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Αποθηκεύτηκε"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Ενεργό (μόνο το αριστερό)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Ενεργό (μόνο το δεξί)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Ενεργό (αριστερό και δεξί)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Ενεργό (μόνο για μέσα). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> μπαταρία."</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Ενεργό (μόνο για μέσα). Α: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Δ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> μπαταρία."</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Συνδεδεμένο (υποστηρίζει κοινή χρήση ήχου). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> μπαταρία."</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Συνδεδεμένο (υποστηρίζει κοινή χρήση ήχου). Α: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Δ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> μπαταρία."</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Συνδεδεμένο (υποστηρίζει κοινή χρήση ήχου). Αριστερά: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> μπαταρία."</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Συνδεδεμένο (υποστηρίζει κοινή χρήση ήχου). Δεξιά: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> μπαταρία."</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Συνδεδεμένο (υποστηρίζει κοινή χρήση ήχου)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Ενεργό (μόνο για μέσα)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Υποστηρίζει κοινή χρήση ήχου"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Ενεργό (μόνο για μέσα), μόνο αριστερό"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Ουδέτερο"</string>
<string name="feminine" msgid="1529155595310784757">"Θηλυκό"</string>
<string name="masculine" msgid="4653978041013996303">"Αρσενικό"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Ενημερώσεις συστήματος"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index 2d80c35..83c1bdc 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -96,10 +96,8 @@
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Connected (no phone or media), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Active. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
<string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Active. L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery."</string>
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Active. L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Active. R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery."</string>
@@ -107,12 +105,9 @@
<string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Right: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Active"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Saved"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Active (left only)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Active (right only)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Active (left and right)"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Active (media only). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Active (media only). L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery."</string>
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Connected (supports audio sharing). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
@@ -726,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Neuter"</string>
<string name="feminine" msgid="1529155595310784757">"Feminine"</string>
<string name="masculine" msgid="4653978041013996303">"Masculine"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"System updates"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index bc08544..59fe8da 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -721,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Neuter"</string>
<string name="feminine" msgid="1529155595310784757">"Feminine"</string>
<string name="masculine" msgid="4653978041013996303">"Masculine"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"System Updates"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index 2d80c35..83c1bdc 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -96,10 +96,8 @@
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Connected (no phone or media), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Active. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
<string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Active. L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery."</string>
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Active. L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Active. R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery."</string>
@@ -107,12 +105,9 @@
<string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Right: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Active"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Saved"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Active (left only)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Active (right only)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Active (left and right)"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Active (media only). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Active (media only). L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery."</string>
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Connected (supports audio sharing). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
@@ -726,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Neuter"</string>
<string name="feminine" msgid="1529155595310784757">"Feminine"</string>
<string name="masculine" msgid="4653978041013996303">"Masculine"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"System updates"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index 2d80c35..83c1bdc 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -96,10 +96,8 @@
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Connected (no phone or media), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Active. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
<string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Active. L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery."</string>
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Active. L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Active. R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery."</string>
@@ -107,12 +105,9 @@
<string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Right: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Active"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Saved"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Active (left only)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Active (right only)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Active (left and right)"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Active (media only). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Active (media only). L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery."</string>
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Connected (supports audio sharing). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
@@ -726,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Neuter"</string>
<string name="feminine" msgid="1529155595310784757">"Feminine"</string>
<string name="masculine" msgid="4653978041013996303">"Masculine"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"System updates"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index b123a13..e7f6d99 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -721,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Neuter"</string>
<string name="feminine" msgid="1529155595310784757">"Feminine"</string>
<string name="masculine" msgid="4653978041013996303">"Masculine"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"System Updates"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 5142f24..0cfae92 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Conectado (sin teléfono) a <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería)"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Conectado (sin archivos multimedia) a <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Conectado (sin teléfono ni archivos multimedia) a <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería)"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Activado. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Activado. I: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>; D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de batería."</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Activo. I: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Activo. D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Batería: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
- <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Activado"</string>
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"I: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>; D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de batería."</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"Izquierdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Derecho: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Activo"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Guardado"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Activo (solo izquierdo)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Activo (solo derecho)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Activos (izquierdo y derecho)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Activado (solo para contenido multimedia). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería."</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Activo (solo para contenido multimedia); I: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>; D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de batería."</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Conectado (admite el uso compartido de audio); <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería."</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Conectado (admite el uso compartido de audio); I: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>; D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de batería."</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Conectado (admite el uso compartido de audio). Izquierdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería."</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Conectado (admite el uso compartido de audio). Derecho: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería."</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Conectado (admite el uso compartido de audio)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Activo (solo para contenido multimedia)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Admite el uso compartido de audio"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Activo (solo para contenido multimedia); solo izquierdo"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Neutro"</string>
<string name="feminine" msgid="1529155595310784757">"Femenino"</string>
<string name="masculine" msgid="4653978041013996303">"Masculino"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Actualizaciones del sistema"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 7dc1225..69c804e 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Conectado (sin audio de teléfono) a <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería)"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Conectado (sin audio multimedia) a <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Conectado (sin audio de teléfono ni multimedia) a <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería)"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Activo. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Activo. Izquierdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de batería. Derecho: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de batería."</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Activo. I: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Activo. D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Batería <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"Izquierdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de batería. Derecho: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de batería."</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"Izquierdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Derecho: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Activo"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Guardado"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Activo (solo izquierdo)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Activo (solo derecho)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Activo (izquierdo y derecho)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Activo (solo multimedia). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería."</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Activo (solo multimedia). Izquierdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de batería. Derecho: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de batería."</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Conectado (permite compartir audio). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería."</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Conectado (admite Compartir audio). Izquierdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de batería. Derecho: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de batería."</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Conectado (admite Compartir audio). Izquierdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería."</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Conectado (admite Compartir audio). Derecho: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería."</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Conectado (admite Compartir audio)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Activo (solo multimedia)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Permite compartir audio"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Activo (solo multimedia), solo el izquierdo"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Neutro"</string>
<string name="feminine" msgid="1529155595310784757">"Femenino"</string>
<string name="masculine" msgid="4653978041013996303">"Masculino"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Actualizaciones del sistema"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index 1236629..fd5762b 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -96,10 +96,8 @@
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Ühendatud (telefoni ega meediat pole), aku <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Aktiivne. Aku <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Aktiivne. Aku: V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, P: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Aktiivne. Vasak: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> akutoidet."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Aktiivne. Parem: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> akutoidet."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> akut"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Akutase: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"Aku: V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, P: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
@@ -107,12 +105,9 @@
<string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Parem: aku <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktiivne"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Salvestatud"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Aktiivne (ainult vasak)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Aktiivne (ainult parem)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Aktiivne (vasak ja parem)"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktiivne (ainult meedia). Aku <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktiivne (ainult meedia). Aku: V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, P: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Ühendatud (toetab heli jagamist). Aku <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
@@ -726,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Kesksugu"</string>
<string name="feminine" msgid="1529155595310784757">"Naissugu"</string>
<string name="masculine" msgid="4653978041013996303">"Meessugu"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Süsteemivärskendused"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 91b9d20be..497fbbb 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Konektatuta (telefonoaren audiorik gabe). Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>."</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Konektatuta (gailuaren audiorik gabe). Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>."</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Konektatuta (telefonoaren edo gailuaren audiorik gabe). Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>."</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Aktibo. Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Aktibo. L aldearen bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>. R aldearen bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Aktibo. Ezkerreko aldearen bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Aktibo. Eskuineko aldearen bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"L aldearen bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>. R aldearen bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"Ezkerreko aldearen bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Eskuineko aldearen bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktibo"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Gordeta"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Aktibo (ezkerrekoa soilik)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Aktibo (eskuinekoa soilik)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Aktibo (ezkerrekoa eta eskuinekoa)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktibo (multimedia-edukia soilik). Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktibo (multimedia-edukia soilik). L aldearen bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>. R aldearen bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Konektatuta (audioa partekatzeko eginbidea onartzen du). Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Konektatuta (audioa partekatzeko eginbidea onartzen du). L aldearen bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>. R aldearen bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Konektatuta (audioa partekatzeko eginbidea onartzen du). Ezkerreko aldearen bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Konektatuta (audioa partekatzeko eginbidea onartzen du). Eskuineko aldearen bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Konektatuta (audioa partekatzeko eginbidea onartzen du)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktibo (multimedia-edukia soilik)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Audioa partekatzeko eginbidea onartzen du"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktibo (multimedia-edukia soilik); ezkerreko aldea soilik"</string>
@@ -302,9 +285,9 @@
<string name="oem_unlock_enable_summary" msgid="5857388174390953829">"Onartu abiarazlea desblokeatzea"</string>
<string name="confirm_enable_oem_unlock_title" msgid="8249318129774367535">"OEM desblokeoa onartu nahi duzu?"</string>
<string name="confirm_enable_oem_unlock_text" msgid="854131050791011970">"ABISUA: ezarpen hau aktibatuta dagoen bitartean, gailua babesteko eginbideek ez dute gailu honetan funtzionatuko."</string>
- <string name="mock_location_app" msgid="6269380172542248304">"Hautatu kokapen faltsuen aplikazioa"</string>
+ <string name="mock_location_app" msgid="6269380172542248304">"Hautatu asmatutako kokapenen aplikazioa"</string>
<string name="mock_location_app_not_set" msgid="6972032787262831155">"Ez da ezarri kokapen faltsuen aplikaziorik"</string>
- <string name="mock_location_app_set" msgid="4706722469342913843">"Kokapen faltsuen aplikazioa: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="mock_location_app_set" msgid="4706722469342913843">"Asmatutako kokapenen aplikazioa: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="debug_networking_category" msgid="6829757985772659599">"Sareak"</string>
<string name="wifi_display_certification" msgid="1805579519992520381">"Hari gabe bistaratzeko ziurtagiria"</string>
<string name="wifi_verbose_logging" msgid="1785910450009679371">"Gaitu wifi-sareetan saioa hasteko modu xehatua"</string>
@@ -653,7 +636,7 @@
<string name="add_user_failed" msgid="4809887794313944872">"Ezin izan da sortu erabiltzailea"</string>
<string name="add_guest_failed" msgid="8074548434469843443">"Ezin izan da sortu beste gonbidatu bat"</string>
<string name="user_nickname" msgid="262624187455825083">"Goitizena"</string>
- <string name="edit_user_info_message" msgid="6677556031419002895">"Gailua erabiltzen duten guztiek ikusi ahal izango dituzte aukeratu dituzun izena eta irudia."</string>
+ <string name="edit_user_info_message" msgid="6677556031419002895">"Gailua erabiltzen duten guztiek ikusi ahal izango dituzte aukeratu dituzun izena eta argazkia."</string>
<string name="user_add_user" msgid="7876449291500212468">"Gehitu erabiltzaile bat"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Gehitu gonbidatu bat"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Kendu gonbidatua"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Neutroa"</string>
<string name="feminine" msgid="1529155595310784757">"Emakumezkoa"</string>
<string name="masculine" msgid="4653978041013996303">"Gizonezkoa"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Sistemaren eguneratzeak"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 7ab13ba..5e7f998 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"متصل (بدون تلفن)، باتری <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"متصل (بدون رسانه)، باتری <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"متصل (بدون تلفن یا رسانه)، باتری <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"فعال. باتری: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"فعال. باتری چپ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>، باتری راست: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"فعال. باتری چپ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"فعال. باتری راست: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> شارژ باتری"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"باتری <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"باتری چپ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>، باتری راست: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"باتری چپ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"باتری راست: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"فعال"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"ذخیرهشده"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"فعال (فقط چپ)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"فعال (فقط راست)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"فعال (چپ و راست)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"فعال (فقط رسانه). باتری: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"فعال (فقط رسانه). باتری چپ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>، باتری راست: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"متصل (از اشتراک صدا پشتیبانی میکند)، باتری: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"متصل (از اشتراک صدا پشتیبانی میکند)، باتری چپ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>، باتری راست: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"متصل (از اشتراک صدا پشتیبانی میکند). باتری چپ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"متصل (از اشتراک صدا پشتیبانی میکند). باتری راست: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"متصل (از اشتراک صدا پشتیبانی میکند)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"فعال (فقط رسانه)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"از اشتراک صدا پشتیبانی میکند"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"فعال (فقط رسانه)، فقط چپ"</string>
@@ -176,7 +159,7 @@
<string name="bluetooth_pairing_decline" msgid="6483118841204885890">"لغو"</string>
<string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"وقتی وصل باشید، مرتبطسازی اجازه دسترسی به مخاطبین و سابقه تماستان را فراهم میکند."</string>
<string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"با <xliff:g id="DEVICE_NAME">%1$s</xliff:g> مرتبطسازی نشد."</string>
- <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"بهدلیل پین یا گذرکلید نادرست، مرتبطسازی با <xliff:g id="DEVICE_NAME">%1$s</xliff:g> انجام نشد."</string>
+ <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"بهدلیل پین یا گذرکلید نادرست، جفتسازی با <xliff:g id="DEVICE_NAME">%1$s</xliff:g> انجام نشد."</string>
<string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"ارتباط با <xliff:g id="DEVICE_NAME">%1$s</xliff:g> امکانپذیر نیست."</string>
<string name="bluetooth_pairing_rejected_error_message" msgid="5943444352777314442">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> مرتبطسازی را رد کرد."</string>
<string name="bluetooth_talkback_computer" msgid="3736623135703893773">"رایانه"</string>
@@ -253,7 +236,7 @@
<string name="category_personal" msgid="6236798763159385225">"شخصی"</string>
<string name="category_work" msgid="4014193632325996115">"کاری"</string>
<string name="category_private" msgid="4244892185452788977">"خصوصی"</string>
- <string name="category_clone" msgid="1554511758987195974">"مشابهسازی"</string>
+ <string name="category_clone" msgid="1554511758987195974">"همسانهسازی"</string>
<string name="development_settings_title" msgid="140296922921597393">"گزینههای برنامهنویسان"</string>
<string name="development_settings_enable" msgid="4285094651288242183">"فعال کردن گزینههای برنامهنویس"</string>
<string name="development_settings_summary" msgid="8718917813868735095">"تنظیم گزینههای مربوط به طراحی برنامه"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"خنثی"</string>
<string name="feminine" msgid="1529155595310784757">"مؤنث"</string>
<string name="masculine" msgid="4653978041013996303">"مذکر"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"بهروزرسانیهای سیستم"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index cafeb1b..bdf4301 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Yhdistetty (ei puhelimen ääntä), akun varaus <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Yhdistetty (ei median ääntä), akun varaus <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Yhdistetty (ei puhelimen tai median ääntä), akun varaustaso <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Aktiivinen. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> virtaa."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Aktiivinen. V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, O: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> virtaa."</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Aktiivinen. V: virtaa <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Aktiivinen. O: virtaa <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Akun taso <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Akku (<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>)"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, O: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> virtaa."</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"Vasen: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> virtaa"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Oikea: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> virtaa."</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktiivinen"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Tallennettu"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Aktiivinen (vain vasen)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Aktiivinen (vain oikea)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Aktiivinen (vasen ja oikea)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktiivinen (vain media). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> virtaa."</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktiivinen (vain media). V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, O: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> virtaa."</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Yhdistetty (tukee audionjakoa). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> virtaa."</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Yhdistetty (tukee audionjakoa). V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> virtaa, O: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> virtaa."</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Yhdistetty (tukee audionjakoa). Vasen: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> virtaa."</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Yhdistetty (tukee audionjakoa). Oikea: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> virtaa."</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Yhdistetty (tukee audionjakoa)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktiivinen (vain media)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Tukee audionjakoa"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktiivinen (vain media), vain vasen"</string>
@@ -176,7 +159,7 @@
<string name="bluetooth_pairing_decline" msgid="6483118841204885890">"Peru"</string>
<string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"Laiteparin muodostaminen mahdollistaa yhteystietojen ja soittohistorian käyttämisen yhteyden aikana."</string>
<string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"Laiteparin muodostaminen laitteeseen <xliff:g id="DEVICE_NAME">%1$s</xliff:g> epäonnistui."</string>
- <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Laiteparia (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>) ei voitu muodostaa, koska PIN tai avain oli väärä."</string>
+ <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Laiteparia (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>) ei voitu muodostaa, koska PIN tai avainkoodi oli väärä."</string>
<string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"Ei yhteyttä laitteeseen <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
<string name="bluetooth_pairing_rejected_error_message" msgid="5943444352777314442">"Laite <xliff:g id="DEVICE_NAME">%1$s</xliff:g> torjui laitepariyhteyden."</string>
<string name="bluetooth_talkback_computer" msgid="3736623135703893773">"Tietokone"</string>
@@ -610,7 +593,7 @@
<string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"Sisäiset kaiuttimet"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Yhteysvirhe. Sammuta laite ja käynnistä se uudelleen."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Langallinen äänilaite"</string>
- <string name="help_label" msgid="3528360748637781274">"Ohje ja palaute"</string>
+ <string name="help_label" msgid="3528360748637781274">"Ohjeet ja palaute"</string>
<string name="storage_category" msgid="2287342585424631813">"Tallennustila"</string>
<string name="shared_data_title" msgid="1017034836800864953">"Jaettu data"</string>
<string name="shared_data_summary" msgid="5516326713822885652">"Katso ja muokkaa jaettua dataa"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Neutri"</string>
<string name="feminine" msgid="1529155595310784757">"Feminiini"</string>
<string name="masculine" msgid="4653978041013996303">"Maskuliini"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Järjestelmäpäivitykset"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index 0eab7c3..090c3b9 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -96,10 +96,8 @@
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Connecté (aucun téléphone ni média), pile chargée à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Actif. Pile à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Actif. G. : pile à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, D. : pile à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Actif. G : pile à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Actif. D : pile à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Pile : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Pile : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"G. : pile à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, D. : pile à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
@@ -107,12 +105,9 @@
<string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Droite : pile à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Actif"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Enregistré"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Actif (gauche seulement)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Actif (droite seulement)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Actif (gauche et droite)"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Actif (contenu multimédia uniquement). Pile à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Actif (contenu multimédia uniquement). G. : pile à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, D. : pile à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Connecté (prise en charge du partage audio). Pile à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
@@ -240,7 +235,7 @@
<string name="choose_profile" msgid="343803890897657450">"Sélectionnez un profil"</string>
<string name="category_personal" msgid="6236798763159385225">"Personnel"</string>
<string name="category_work" msgid="4014193632325996115">"Professionnel"</string>
- <string name="category_private" msgid="4244892185452788977">"Privés"</string>
+ <string name="category_private" msgid="4244892185452788977">"Privé"</string>
<string name="category_clone" msgid="1554511758987195974">"Cloner"</string>
<string name="development_settings_title" msgid="140296922921597393">"Options pour les développeurs"</string>
<string name="development_settings_enable" msgid="4285094651288242183">"Activer les options pour les développeurs"</string>
@@ -290,7 +285,7 @@
<string name="oem_unlock_enable_summary" msgid="5857388174390953829">"Autoriser le déverrouillage du fichier d\'amorce"</string>
<string name="confirm_enable_oem_unlock_title" msgid="8249318129774367535">"Permettre le déverrouillage par le fabricant?"</string>
<string name="confirm_enable_oem_unlock_text" msgid="854131050791011970">"AVERTISSEMENT : Les fonctionnalités de protection de l\'appareil ne fonctionneront pas sur cet appareil lorsque ce paramètre est activé."</string>
- <string name="mock_location_app" msgid="6269380172542248304">"Sélectionner l\'application de position fictive"</string>
+ <string name="mock_location_app" msgid="6269380172542248304">"Sélectionner l\'appli de position fictive"</string>
<string name="mock_location_app_not_set" msgid="6972032787262831155">"Aucune application de position fictive définie"</string>
<string name="mock_location_app_set" msgid="4706722469342913843">"Application de position fictive : <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="debug_networking_category" msgid="6829757985772659599">"Réseautage"</string>
@@ -726,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Neutre"</string>
<string name="feminine" msgid="1529155595310784757">"Féminin"</string>
<string name="masculine" msgid="4653978041013996303">"Masculin"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Mises à jour du système"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 1928f32..be3b058 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Connecté (aucun téléphone), batterie à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Connecté (aucun contenu multimédia), batterie à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Connecté (aucun téléphone ni contenu multimédia), batterie à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Actif. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batterie."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Actif. Gauche : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de batterie, droit : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de batterie."</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Actif. G : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batterie."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Actif. D : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batterie."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batterie"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Batterie (<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>)"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"Gauche : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de batterie, droit : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de batterie."</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"Gauche : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batterie"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Droit : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batterie"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Actif"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Enregistré"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Actif (gauche uniquement)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Actif (droit uniquement)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Actifs (gauche et droit)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Actif (multimédia uniquement). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batterie."</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Actif (multimédia uniquement). Gauche : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de batterie, droit : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de batterie."</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Connecté (compatible avec le partage audio). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batterie."</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Connecté (compatible avec le partage audio). Gauche : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de batterie, droit : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de batterie."</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Connecté (compatible avec le partage audio). Gauche : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batterie."</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Connecté (compatible avec le partage audio). Droit : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batterie."</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Connecté (compatible avec le partage audio)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Activé (multimédia uniquement)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Compatible avec le partage audio"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Activé (multimédia uniquement), gauche uniquement"</string>
@@ -249,7 +232,7 @@
<item msgid="4446831566506165093">"350 %"</item>
<item msgid="6946761421234586000">"400 %"</item>
</string-array>
- <string name="choose_profile" msgid="343803890897657450">"Sélectionner un profil"</string>
+ <string name="choose_profile" msgid="343803890897657450">"Choisissez un profil"</string>
<string name="category_personal" msgid="6236798763159385225">"Perso"</string>
<string name="category_work" msgid="4014193632325996115">"Pro"</string>
<string name="category_private" msgid="4244892185452788977">"Privé"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Neutre"</string>
<string name="feminine" msgid="1529155595310784757">"Féminin"</string>
<string name="masculine" msgid="4653978041013996303">"Masculin"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Mises à jour du système"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index d0f47a8..21d0bcd 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Conectado a <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (sen teléfono), batería ao <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Conectado a <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (sen audio multimedia), batería ao <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Conectado a <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (sen teléfono nin audio multimedia), batería ao <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Activo. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Activo. Esquerdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de batería. Dereito: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de batería."</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Activo. Esquerdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Activo. Dereito: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Batería: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"Esquerdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de batería. Dereito: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de batería."</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"Esquerdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería."</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Dereito: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería."</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Activo"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Gardado"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Activo (só o esquerdo)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Activo (só o dereito)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Activos (o esquerdo e o dereito)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Activo (só contido multimedia). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería."</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Activo (só contido multimedia). Esquerdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de batería. Dereito: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de batería."</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Conectado (compatible con audio compartido). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería."</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Conectado (compatible con audio compartido). Esquerdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de batería. Dereito: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de batería."</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Conectado (compatible con audio compartido). Esquerdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería."</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Conectado (compatible con audio compartido). Dereito: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería."</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Conectado (compatible con audio compartido)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Activo (só contido multimedia)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Compatible con audio compartido"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Activo (só contido multimedia), só esquerdo"</string>
@@ -176,7 +159,7 @@
<string name="bluetooth_pairing_decline" msgid="6483118841204885890">"Cancelar"</string>
<string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"A vinculación garante acceso aos teus contactos e ao historial de chamadas ao estar conectado"</string>
<string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"Non se puido vincular con <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
- <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Non se puido vincular con <xliff:g id="DEVICE_NAME">%1$s</xliff:g>, clave de acceso ou PIN incorrectos."</string>
+ <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Non se puido vincular con <xliff:g id="DEVICE_NAME">%1$s</xliff:g>; clave de acceso ou PIN incorrectos."</string>
<string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"Non se pode comunicar con <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
<string name="bluetooth_pairing_rejected_error_message" msgid="5943444352777314442">"Vinculación rexeitada por <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
<string name="bluetooth_talkback_computer" msgid="3736623135703893773">"Ordenador"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Neutro"</string>
<string name="feminine" msgid="1529155595310784757">"Feminino"</string>
<string name="masculine" msgid="4653978041013996303">"Masculino"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Actualizacións do sistema"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index ef53786..35f48e0 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -96,10 +96,8 @@
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> સાથે કનેક્ટ થયેલ (કોઈ ફોન અથવા મીડિયા નથી), બૅટરી <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_active_battery_level" msgid="2685517576209066008">"સક્રિય. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> બૅટરી."</string>
<string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"સક્રિય. ડાબી બાજુ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, જમણી બાજુ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> બૅટરી."</string>
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"ચાલુ છે. ડાબી બાજુ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> બૅટરી."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"ચાલુ છે. જમણી બાજુ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> બૅટરી."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> બૅટરી"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"બૅટરી <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"ડાબી બાજુ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, જમણી બાજુ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> બૅટરી."</string>
@@ -107,12 +105,9 @@
<string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"જમણી બાજુ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> બૅટરી"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"સક્રિય"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"સાચવેલું"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"ચાલુ છે (માત્ર ડાબી બાજુ)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"ચાલુ છે (માત્ર જમણી બાજુ)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"ચાલુ છે (ડાબી અને જમણી બાજુ)"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"સક્રિય (માત્ર મીડિયા માટે). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> બૅટરી."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"સક્રિય (માત્ર મીડિયા માટે). ડાબી બાજુ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, જમણી બાજુ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> બૅટરી."</string>
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"કનેક્ટેડ (ઑડિયો શેરિંગને સપોર્ટ કરે છે). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> બૅટરી."</string>
@@ -292,7 +287,7 @@
<string name="confirm_enable_oem_unlock_text" msgid="854131050791011970">"ચેતવણી: જ્યારે આ સેટિંગ ચાલુ હોય ત્યારે આ ઉપકરણ પર ઉપકરણ સંરક્ષણ સુવિધાઓ કાર્ય કરશે નહીં."</string>
<string name="mock_location_app" msgid="6269380172542248304">"મોક લોકેશન ઍપ પસંદ કરો"</string>
<string name="mock_location_app_not_set" msgid="6972032787262831155">"કોઈ મોક લોકેશન ઍપ સેટ કરાયેલું નથી"</string>
- <string name="mock_location_app_set" msgid="4706722469342913843">"મોક સ્થાન ઍપ્લિકેશન: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="mock_location_app_set" msgid="4706722469342913843">"મૉક લોકેશન ઍપ: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="debug_networking_category" msgid="6829757985772659599">"નેટવર્કિંગ"</string>
<string name="wifi_display_certification" msgid="1805579519992520381">"વાયરલેસ ડિસ્પ્લે પ્રમાણન"</string>
<string name="wifi_verbose_logging" msgid="1785910450009679371">"વાઇ-ફાઇ વર્બોઝ લૉગિંગ ચાલુ કરો"</string>
@@ -601,7 +596,7 @@
<string name="help_label" msgid="3528360748637781274">"સહાય અને પ્રતિસાદ"</string>
<string name="storage_category" msgid="2287342585424631813">"સ્ટોરેજ"</string>
<string name="shared_data_title" msgid="1017034836800864953">"શેર કરેલો ડેટા"</string>
- <string name="shared_data_summary" msgid="5516326713822885652">"શેર કરેલા ડેટાને જુઓ અને તેને સંશોધિત કરો"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"શેર કરેલા ડેટાને જુઓ અને તેમાં ફેરફાર કરો"</string>
<string name="shared_data_no_blobs_text" msgid="3108114670341737434">"આ વપરાશકર્તા માટે કોઈ શેર કરેલો ડેટા નથી."</string>
<string name="shared_data_query_failure_text" msgid="3489828881998773687">"શેર કરેલો ડેટા મેળવવામાં ભૂલ આવી હતી. ફરી પ્રયાસ કરો."</string>
<string name="blob_id_text" msgid="8680078988996308061">"શેર કરેલા ડેટાનું ID: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
@@ -726,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"નાન્યતર"</string>
<string name="feminine" msgid="1529155595310784757">"સ્ત્રીલિંગી"</string>
<string name="masculine" msgid="4653978041013996303">"પુલ્લિંગી"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"સિસ્ટમ અપડેટ"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 9499120..e434d1e 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -287,7 +287,7 @@
<string name="confirm_enable_oem_unlock_text" msgid="854131050791011970">"चेतावनी: इस सेटिंग के चालू रहने पर डिवाइस सुरक्षा सुविधाएं इस डिवाइस पर काम नहीं करेंगी."</string>
<string name="mock_location_app" msgid="6269380172542248304">"मॉक लोकेशन के लिए ऐप्लिकेशन चुनें"</string>
<string name="mock_location_app_not_set" msgid="6972032787262831155">"मॉक लोकेशन के लिए ऐप्लिकेशन सेट नहीं है"</string>
- <string name="mock_location_app_set" msgid="4706722469342913843">"जगह की दिखावटी जानकारी देने वाला ऐप: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="mock_location_app_set" msgid="4706722469342913843">"मॉक लोकेशन के लिए ऐप्लिकेशन: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="debug_networking_category" msgid="6829757985772659599">"नेटवर्किंग"</string>
<string name="wifi_display_certification" msgid="1805579519992520381">"वायरलेस डिसप्ले सर्टिफ़िकेशन"</string>
<string name="wifi_verbose_logging" msgid="1785910450009679371">"वाई-फ़ाई वर्बोस लॉगिंग चालू करें"</string>
@@ -370,7 +370,7 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"हार्डवेयर ऐक्सेलरेटेड रेंडरिंग"</string>
<string name="media_category" msgid="8122076702526144053">"मीडिया"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"निगरानी"</string>
- <string name="strict_mode" msgid="889864762140862437">"स्ट्रिक्ट मोड चालू किया गया"</string>
+ <string name="strict_mode" msgid="889864762140862437">"स्ट्रिक्ट मोड चालू रखें"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"थ्रेड पर लंबा प्रोसेस होने पर स्क्रीन फ़्लैश करें"</string>
<string name="pointer_location" msgid="7516929526199520173">"पॉइंटर की जगह"</string>
<string name="pointer_location_summary" msgid="957120116989798464">"मौजूदा टच डेटा दिखाने वाला स्क्रीन ओवरले"</string>
@@ -721,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"नपुंसक लिंग"</string>
<string name="feminine" msgid="1529155595310784757">"महिला"</string>
<string name="masculine" msgid="4653978041013996303">"पुरुष"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"सिस्टम अपडेट"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index db2c318..0aba7cd 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Povezano (bez telefona), baterija <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Povezano (bez medija), baterija <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Povezano (bez telefona i medija), baterija <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Aktivno. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Aktivno. L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> baterije."</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Aktivno. L: baterija na <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Aktivno. D: baterija na <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Baterija <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> baterije."</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"Lijeva strana: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Desna strana: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktivan"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Spremljeno"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Aktivno (samo lijevo)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Aktivno (samo desno)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Aktivno (lijevo i desno)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktivno (samo medijski sadržaji). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije."</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktivno (samo medijski sadržaji), L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> baterije."</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Povezano (podržava zajedničko slušanje). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije."</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Povezano (podržava zajedničko slušanje), L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> baterije."</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Povezano (podržava zajedničko slušanje). Lijeva strana: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije"</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Povezano (podržava zajedničko slušanje). Desna strana: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije."</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Povezano (podržava zajedničko slušanje)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktivno (samo medijski sadržaji)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Podržava zajedničko slušanje"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktivno (samo medijski sadržaji), samo lijeva"</string>
@@ -406,7 +389,7 @@
<string name="disable_overlays_summary" msgid="1954852414363338166">"Uvijek se koristi GPU za slaganje zaslona"</string>
<string name="simulate_color_space" msgid="1206503300335835151">"Simulacija prostora boja"</string>
<string name="enable_opengl_traces_title" msgid="4638773318659125196">"Omogući OpenGL praćenja"</string>
- <string name="usb_audio_disable_routing" msgid="3367656923544254975">"Onemogući USB audiousmj."</string>
+ <string name="usb_audio_disable_routing" msgid="3367656923544254975">"Onemogući USB audiousmjeravanje"</string>
<string name="usb_audio_disable_routing_summary" msgid="8768242894849534699">"Onemogućuje se automatsko usmjeravanje na USB audioperiferiju"</string>
<string name="debug_layout" msgid="1659216803043339741">"Prikaži okvir prikaza"</string>
<string name="debug_layout_summary" msgid="8825829038287321978">"Prikazuju se obrubi, margine itd. isječaka"</string>
@@ -613,7 +596,7 @@
<string name="help_label" msgid="3528360748637781274">"Pomoć i povratne informacije"</string>
<string name="storage_category" msgid="2287342585424631813">"Pohrana"</string>
<string name="shared_data_title" msgid="1017034836800864953">"Dijeljeni podaci"</string>
- <string name="shared_data_summary" msgid="5516326713822885652">"Prikaz i izmjena dijeljenih podataka"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Pogledajte i izmjenite dijeljene podatke"</string>
<string name="shared_data_no_blobs_text" msgid="3108114670341737434">"Nema dijeljenih podataka za ovog korisnika."</string>
<string name="shared_data_query_failure_text" msgid="3489828881998773687">"Došlo je do pogreške prilikom dohvaćanja dijeljenih podataka. Pokušajte ponovno."</string>
<string name="blob_id_text" msgid="8680078988996308061">"ID dijeljenih podataka: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Srednji rod"</string>
<string name="feminine" msgid="1529155595310784757">"Ženski rod"</string>
<string name="masculine" msgid="4653978041013996303">"Muški rod"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Ažuriranja sustava"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 207e84a..e01c20a 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Csatlakoztatva (telefonhang nélkül); az akkumulátor töltöttségi szintje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Csatlakoztatva (médiahang nélkül); az akkumulátor töltöttségi szintje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Csatlakoztatva (nincs telefon- és médiahang); az akkumulátor töltöttségi szintje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Aktív. Akkumulátor töltöttségi szintje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Aktív. Akkumulátorok töltöttségi szintje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> (bal) és <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> (jobb)."</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Aktív. Akku: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> (bal)."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Aktív. Akku: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> (jobb)."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Akkumulátor: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Akkumulátor: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"Akkumulátorok töltöttségi szintje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> (bal) és <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> (jobb)."</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"Akkumulátor töltöttségi szintje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> (bal)."</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Akkumulátor töltöttségi szintje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> (jobb)."</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktív"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Mentve"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Aktív (csak bal)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Aktív (csak jobb)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Aktív (bal és jobb)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktív (csak médiatartalom lejátszása esetén). Akkumulátor töltöttségi szintje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktív (csak médiatartalom lejátszása esetén). Akkumulátorok töltöttségi szintje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> (bal) és <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> (jobb)."</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Csatlakoztatva (támogatja a hang megosztását). Akkumulátor töltöttségi szintje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Csatlakoztatva (támogatja a hang megosztását). Akkumulátorok töltöttségi szintje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> (bal) és <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> (jobb)."</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Csatlakoztatva (támogatja a hang megosztását). Akkumulátor töltöttségi szintje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> (bal)."</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Csatlakoztatva (támogatja a hang megosztását). Akkumulátor töltöttségi szintje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> (jobb)."</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Csatlakoztatva (támogatja a hang megosztását)."</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktív (csak médiatartalom lejátszása)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Támogatja a hang megosztását"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktív (csak médiatartalom lejátszása), csak a bal"</string>
@@ -406,7 +389,7 @@
<string name="disable_overlays_summary" msgid="1954852414363338166">"Mindig a GPU használata képernyő-feldolgozáshoz"</string>
<string name="simulate_color_space" msgid="1206503300335835151">"Színtérszimuláció"</string>
<string name="enable_opengl_traces_title" msgid="4638773318659125196">"OpenGL nyomon követése"</string>
- <string name="usb_audio_disable_routing" msgid="3367656923544254975">"Hangátirányítás tiltása"</string>
+ <string name="usb_audio_disable_routing" msgid="3367656923544254975">"Hangátirányítás tiltása - USB"</string>
<string name="usb_audio_disable_routing_summary" msgid="8768242894849534699">"Hangátirányítás tiltása az USB-s hangeszközöknél"</string>
<string name="debug_layout" msgid="1659216803043339741">"Elrendezéshatárok"</string>
<string name="debug_layout_summary" msgid="8825829038287321978">"Kliphatárok, margók stb. megjelenítése."</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Semleges nemű alak"</string>
<string name="feminine" msgid="1529155595310784757">"Női"</string>
<string name="masculine" msgid="4653978041013996303">"Férfi"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Rendszerfrissítések"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index 1b8b236..4c0712c 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Միացված է (հեռախոս չկա), մարտկոցի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Միացված է (մեդիա չկա), մարտկոցի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Միացված է (հեռախոս կամ մեդիա չկա), մարտկոցի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Ակտիվ է։ Մարտկոցի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>։"</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Ակտիվ է։ Ձախ ականջակալի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, աջ ականջակալի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>։"</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Ակտիվ է։ Ձախ․ մարտկոցի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>։"</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Ակտիվ է։ Աջ․ մարտկոցի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>։"</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Մարտկոցի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Մարտկոցի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"Ձախ ականջակալի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, աջ ականջակալի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>։"</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"Ձախ ականջակալի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Աջ ականջակալի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Ակտիվ է"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Պահված է"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Ակտիվ է (միայն ձախ)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Ակտիվ է (միայն աջ)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Ակտիվ է (ձախ և աջ)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Ակտիվ է (միայն մեդիա)։ Մարտկոցի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>։"</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Ակտիվ է (միայն մեդիա)։ Ձախ ականջակալի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, աջ ականջակալի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>։"</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Միացված է (աջակցում է աուդիոյի փոխանցում)։ Մարտկոցի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>։"</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Միացված է (աջակցում է աուդիոյի փոխանցում)։ Ձախ ականջակալի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, աջ ականջակալի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>։"</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Միացված է (աջակցում է աուդիոյի փոխանցում)։ Ձախ ականջակալի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>։"</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Միացված է (աջակցում է աուդիոյի փոխանցում)։ Աջ ականջակալի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>։"</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Միացված է (աջակցում է աուդիոյի փոխանցում)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Ակտիվ է (միայն մեդիա)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Աջակցում է աուդիոյի փոխանցում"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Ակտիվ է (միայն մեդիա), միայն ձախ"</string>
@@ -612,8 +595,8 @@
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Լարով աուդիո սարք"</string>
<string name="help_label" msgid="3528360748637781274">"Օգնություն և հետադարձ կապ"</string>
<string name="storage_category" msgid="2287342585424631813">"Տարածք"</string>
- <string name="shared_data_title" msgid="1017034836800864953">"Հասանելի դարձված տվյալներ"</string>
- <string name="shared_data_summary" msgid="5516326713822885652">"Դիտեք և փոփոխեք հասանելի դարձված տվյալները"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Ընդհանուր տվյալներ"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Դիտեք և փոփոխեք ընդհանուր տվյալները"</string>
<string name="shared_data_no_blobs_text" msgid="3108114670341737434">"Այս օգտատիրոջ համար ընդհանուր տվյալներ չկան։"</string>
<string name="shared_data_query_failure_text" msgid="3489828881998773687">"Չհաջողվեց բեռնել ընդհանուր տվյալները։ Նորից փորձեք։"</string>
<string name="blob_id_text" msgid="8680078988996308061">"Հասանելի դարձված տվյալների ID՝ <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
@@ -623,7 +606,7 @@
<string name="accessor_info_title" msgid="8289823651512477787">"Տվյալներով կիսվող հավելվածներ"</string>
<string name="accessor_no_description_text" msgid="7510967452505591456">"Հավելվածի կողմից տրամադրված նկարագրություն չկա։"</string>
<string name="accessor_expires_text" msgid="4625619273236786252">"Վարձակալության ժակետն ավարտվում է՝ <xliff:g id="DATE">%s</xliff:g>"</string>
- <string name="delete_blob_text" msgid="2819192607255625697">"Ջնջել հասանելի դարձված տվյալները"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Ջնջել ընդհանուր տվյալները"</string>
<string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Իսկապե՞ս ուզում եք ջնջել հասանելի դարձված այս տվյալները։"</string>
<string name="user_add_user_item_summary" msgid="5748424612724703400">"Օգտվողներն իրենց անձնական հավելվածներն ու բովանդակությունն ունեն"</string>
<string name="user_add_profile_item_summary" msgid="5418602404308968028">"Դուք կարող եք սահմանափակել մուտքի իրավունքը ծրագրեր և ձեր հաշվի բովանդակություն:"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Չեզոք"</string>
<string name="feminine" msgid="1529155595310784757">"Իգական"</string>
<string name="masculine" msgid="4653978041013996303">"Արական"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Համակարգի թարմացումներ"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index d9730b3..79fb4da 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Terhubung (tanpa ponsel), baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Terhubung (tanpa media), baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Terhubung (tanpa ponsel atau media), baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Aktif. Baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Aktif. Baterai L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Aktif. L: Baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Aktif. R: Baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"Baterai L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"Kiri: Baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Kanan: Baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktif"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Disimpan"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Aktif (hanya kiri)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Aktif (hanya kanan)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Aktif (kiri dan kanan)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktif (hanya media). Baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktif (hanya media). Baterai L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Terhubung (mendukung berbagi audio). Baterai<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Terhubung (mendukung berbagi audio). Baterai L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Terhubung (mendukung berbagi audio). Kiri: Baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Terhubung (mendukung berbagi audio). Kanan: Baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Terhubung (mendukung berbagi audio)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktif (hanya media)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Mendukung berbagi audio"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktif (hanya media), hanya kiri"</string>
@@ -252,7 +235,7 @@
<string name="choose_profile" msgid="343803890897657450">"Pilih profil"</string>
<string name="category_personal" msgid="6236798763159385225">"Pribadi"</string>
<string name="category_work" msgid="4014193632325996115">"Kerja"</string>
- <string name="category_private" msgid="4244892185452788977">"Pribadi"</string>
+ <string name="category_private" msgid="4244892185452788977">"Privasi"</string>
<string name="category_clone" msgid="1554511758987195974">"Clone"</string>
<string name="development_settings_title" msgid="140296922921597393">"Opsi developer"</string>
<string name="development_settings_enable" msgid="4285094651288242183">"Aktifkan opsi developer"</string>
@@ -386,9 +369,9 @@
<string name="debug_drawing_category" msgid="5066171112313666619">"Gambar"</string>
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Render yang dipercepat hardware"</string>
<string name="media_category" msgid="8122076702526144053">"Media"</string>
- <string name="debug_monitoring_category" msgid="1597387133765424994">"Memantau"</string>
+ <string name="debug_monitoring_category" msgid="1597387133765424994">"Pemantauan"</string>
<string name="strict_mode" msgid="889864762140862437">"Mode ketat diaktifkan"</string>
- <string name="strict_mode_summary" msgid="1838248687233554654">"Buat layar berkedip saat aplikasi berjalan lama di thread utama"</string>
+ <string name="strict_mode_summary" msgid="1838248687233554654">"Buat layar berkedip saat aplikasi berlama-lama menjalankan operasi di thread utama"</string>
<string name="pointer_location" msgid="7516929526199520173">"Lokasi kursor"</string>
<string name="pointer_location_summary" msgid="957120116989798464">"Overlay layar menampilkan data sentuhan saat ini"</string>
<string name="show_touches" msgid="8437666942161289025">"Tampilkan ketukan"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Netral"</string>
<string name="feminine" msgid="1529155595310784757">"Feminin"</string>
<string name="masculine" msgid="4653978041013996303">"Maskulin"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Update Sistem"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index 60370f5..dfb780d 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Tengt (enginn sími), staða rafhlöðu <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Tengt (ekkert efni), staða rafhlöðu <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Tengt (enginn sími eða efni), staða rafhlöðu <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Virkt. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> rafhlöðuhleðsla."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Virkt. V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, H: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> rafhlöðuhleðsla."</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Kveikt. V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> hleðsla."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Kveikt. H: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> hleðsla."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> rafhlöðuhleðsla"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Rafhlaða <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, H: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> rafhlöðuhleðsla."</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"Vinstri: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> rafhlöðuhleðsla"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Hægri: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> rafhlöðuhleðsla"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Virkt"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Vistað"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Kveikt (eingöngu vinstra)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Kveikt (eingöngu hægra)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Kveikt (vinstra og hægra)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Virkt (eingöngu margmiðlunarefni). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> rafhlöðuhleðsla."</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Virkt (eingöngu margmiðlunarefni), V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, H: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> rafhlöðuhleðsla."</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Tengt (styður hljóðdeilingu), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> rafhlöðuhleðsla."</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Tengt (styður hljóðdeilingu), V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, H: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> rafhlöðuhleðsla."</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Tengt (styður hljóðdeilingu). Vinstri: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> rafhlöðuhleðsla."</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Tengt (styður hljóðdeilingu). Hægri: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> rafhlöðuhleðsla."</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Tengt (styður hljóðdeilingu)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Virkt (eingöngu margmiðlunarefni)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Styður hljóðdeilingu"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Virkt (eingöngu margmiðlunarefni), eingöngu vinstri"</string>
@@ -196,7 +179,7 @@
<string name="accessibility_wifi_other_device" msgid="2815627624555795918">"Tengt við tækið þitt."</string>
<string name="accessibility_wifi_security_type_none" msgid="162352241518066966">"Opið net"</string>
<string name="accessibility_wifi_security_type_secured" msgid="2399774097343238942">"Öruggt net"</string>
- <string name="process_kernel_label" msgid="950292573930336765">"Android stýrikerfið"</string>
+ <string name="process_kernel_label" msgid="950292573930336765">"Android-stýrikerfið"</string>
<string name="data_usage_uninstalled_apps" msgid="1933665711856171491">"Fjarlægð forrit"</string>
<string name="data_usage_uninstalled_apps_users" msgid="5533981546921913295">"Fjarlægð forrit og notendur"</string>
<string name="data_usage_ota" msgid="7984667793701597001">"Kerfisuppfærslur"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Kynsegin"</string>
<string name="feminine" msgid="1529155595310784757">"Kvenkyn"</string>
<string name="masculine" msgid="4653978041013996303">"Karlkyn"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Kerfisuppfærslur"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index fbae08d..26b9c64 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> connesso (telefono escluso), batteria al <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> connesso (contenuti multimediali esclusi), batteria al <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> connesso (telefono o contenuti multimediali esclusi), batteria al <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Attivo. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> di batteria."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Attivo. S: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> di batteria. D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> di batteria."</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Attivo. S: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> di batteria."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Attivo. D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> di batteria."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Batteria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Batteria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"S: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> di batteria. D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> di batteria."</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"Sinistro: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> di batteria"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Destro: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> di batteria"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Attivo"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Dispositivo salvato"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Attivo (solo sinistro)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Attivo (solo destro)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Attivi (destro e sinistro)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Attivo (solo contenuti multimediali). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> di batteria."</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Attivo (solo contenuti multimediali). S: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> di batteria. D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> di batteria."</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Connesso (supporta la condivisione audio). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> di batteria."</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Connesso (supporta la condivisione audio). S: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> di batteria. D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> di batteria."</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Connesso (supporta la condivisione audio). Sinistro: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> di batteria."</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Connesso (supporta la condivisione audio). Destro: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> di batteria."</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Connesso (supporta la condivisione audio)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Attivo (solo contenuti multimediali)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Supporta la condivisione audio"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Attivo (solo contenuti multimediali), solo sinistro"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Neutro"</string>
<string name="feminine" msgid="1529155595310784757">"Femminile"</string>
<string name="masculine" msgid="4653978041013996303">"Maschile"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Aggiornamenti di sistema"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 5a6c751..c232396 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"מחובר (ללא טלפון), שיעור הסוללה <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"מחובר (ללא מדיה), שיעור הסוללה <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"מחובר (ללא טלפון או מדיה), שיעור הסוללה <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"פעיל. סוללה: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"פעיל. סוללה בצד שמאל: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, סוללה בצד ימין: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"פעיל. סוללה בצד שמאל: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"פעיל. סוללה בצד ימין: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"טעינת הסוללה: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"סוללה <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"סוללה בצד שמאל: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, סוללה בצד ימין: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"סוללה בצד שמאל: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"סוללה בצד ימין: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"פעיל"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"בוצעה שמירה"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"פעיל (שמאל בלבד)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"פעיל (ימין בלבד)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"פעיל (ימין ושמאל)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"פעיל (מדיה בלבד). סוללה: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"פעיל (מדיה בלבד). סוללה בצד שמאל: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, סוללה בצד ימין: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"מחובר (תמיכה בשיתוף אודיו). סוללה: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"מחובר (תמיכה בשיתוף אודיו). סוללה בצד שמאל: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, סוללה בצד ימין: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"מחובר (תמיכה בשיתוף אודיו). סוללה בצד שמאל: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"מחובר (תמיכה בשיתוף אודיו). סוללה בצד ימין: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"מחובר (תמיכה בשיתוף אודיו)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"פעיל (מדיה בלבד)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"תמיכה בשיתוף אודיו"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"פעיל (מדיה בלבד), שמאל בלבד"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"ניטרלי"</string>
<string name="feminine" msgid="1529155595310784757">"נקבה"</string>
<string name="masculine" msgid="4653978041013996303">"זכר"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"עדכוני מערכת"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 26bf76e..4d2f8fc 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -96,10 +96,8 @@
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"接続済み(電話、メディアなし)、バッテリー残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>: <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_active_battery_level" msgid="2685517576209066008">"有効。バッテリー残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>。"</string>
<string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"有効。左: バッテリー残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>、右: バッテリー残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>。"</string>
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"アクティブ。左: バッテリー残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>。"</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"アクティブ。右: バッテリー残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>。"</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"バッテリー <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"バッテリー <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"左: バッテリー残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>、右: バッテリー残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>。"</string>
@@ -107,12 +105,9 @@
<string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"右: バッテリー残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"有効"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"保存済み"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"アクティブ(左のみ)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"アクティブ(右のみ)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"アクティブ(左と右)"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"有効(メディアのみ)。バッテリー残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>。"</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"有効(メディアのみ)。左: バッテリー残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>、右: バッテリー残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>。"</string>
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"接続済み(音声の共有をサポート)。バッテリー残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>。"</string>
@@ -240,7 +235,7 @@
<string name="choose_profile" msgid="343803890897657450">"プロファイルの選択"</string>
<string name="category_personal" msgid="6236798763159385225">"個人用"</string>
<string name="category_work" msgid="4014193632325996115">"仕事用"</string>
- <string name="category_private" msgid="4244892185452788977">"非公開"</string>
+ <string name="category_private" msgid="4244892185452788977">"プライベート"</string>
<string name="category_clone" msgid="1554511758987195974">"クローン"</string>
<string name="development_settings_title" msgid="140296922921597393">"開発者向けオプション"</string>
<string name="development_settings_enable" msgid="4285094651288242183">"開発者向けオプションの有効化"</string>
@@ -726,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"中性"</string>
<string name="feminine" msgid="1529155595310784757">"女性"</string>
<string name="masculine" msgid="4653978041013996303">"男性"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"システム アップデート"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index 266a557..4ade50f 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -98,10 +98,8 @@
<!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
<skip />
<string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"აქტიური. მარცხენა: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, მარჯვენა: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ბატარეა."</string>
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"აქტიური. მარცხენა ბატარეის დონე: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"აქტიური. მარჯვენა ბატარეის დონე: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ბატარეა"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"ბატარეა <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"მარცხენა: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, მარჯვენა: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ბატარეა."</string>
@@ -109,12 +107,9 @@
<string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"მარჯვენა: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ბატარეა"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"აქტიური"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"შენახული"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"აქტიური (მხოლოდ მარცხენა)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"აქტიური (მხოლოდ მარჯვენა)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"აქტიური (მარცხენა და მარჯვენა)"</string>
<!-- String.format failed for translation -->
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
@@ -244,7 +239,7 @@
<string name="choose_profile" msgid="343803890897657450">"აირჩიეთ პროფილი"</string>
<string name="category_personal" msgid="6236798763159385225">"პირადი"</string>
<string name="category_work" msgid="4014193632325996115">"სამსახური"</string>
- <string name="category_private" msgid="4244892185452788977">"პირადი"</string>
+ <string name="category_private" msgid="4244892185452788977">"კერძო"</string>
<string name="category_clone" msgid="1554511758987195974">"კლონის შექმნა"</string>
<string name="development_settings_title" msgid="140296922921597393">"პარამეტრები დეველოპერებისთვის"</string>
<string name="development_settings_enable" msgid="4285094651288242183">"დეველოპერთა პარამეტრების ჩართვა"</string>
@@ -730,4 +725,5 @@
<string name="neuter" msgid="2075249330106127310">"საშუალო"</string>
<string name="feminine" msgid="1529155595310784757">"მდედრობითი"</string>
<string name="masculine" msgid="4653978041013996303">"მამრობითი"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"სისტემური განახლებები"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index eee0ac6..4e034b4 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Жалғанды (телефонсыз), батарея заряды: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Жалғанды (аудиосыз), батарея заряды: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Жалғанды (телефонсыз не аудиосыз), батарея заряды: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Істеп тұр. Батарея зарядының деңгейі – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Істеп тұр. Сол жақ: батарея зарядының деңгейі – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>. Оң жақ: батарея зарядының деңгейі — <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Істеп тұр. Сол жақ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> қуат."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Істеп тұр. Оң жақ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> қуат."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Батарея қуаты: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Батарея: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"Сол жақ: батарея зарядының деңгейі – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>. Оң жақ: батарея зарядының деңгейі — <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"Сол жақ: батарея зарядының деңгейі – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Оң жақ: батарея зарядының деңгейі – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Қосулы"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Сақталған"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Істеп тұр (тек сол жағы)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Істеп тұр (тек оң жағы)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Істеп тұр (екі жағы да)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Істеп тұр (тек мультимедиа). Батарея зарядының деңгейі – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Істеп тұр (тек мультимедиа). Сол жақ: батарея зарядының деңгейі — <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>. Оң жақ: батарея зарядының деңгейі — <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Қосылды (аудио бөлісуге мүмкіндік береді). Батарея зарядының деңгейі:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Қосылды (аудио бөлісуге мүмкіндік береді). Сол жақ: батарея зарядының деңгейі — <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>. Оң жақ: батарея зарядының деңгейі — <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Қосылды (аудио бөлісуге мүмкіндік береді). Сол жақ: батарея зарядының деңгейі – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Қосылды (аудио бөлісуге мүмкіндік береді). Оң жақ: батарея зарядының деңгейі – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Қосылды (аудио бөлісуге мүмкіндік береді)."</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Істеп тұр (тек мультимедиа)."</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Аудио бөлісуге мүмкіндік береді."</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Тек сол жақ істеп тұр (мультимедиа ғана)."</string>
@@ -252,7 +235,7 @@
<string name="choose_profile" msgid="343803890897657450">"Профильді таңдау"</string>
<string name="category_personal" msgid="6236798763159385225">"Жеке"</string>
<string name="category_work" msgid="4014193632325996115">"Жұмыс"</string>
- <string name="category_private" msgid="4244892185452788977">"Жеке"</string>
+ <string name="category_private" msgid="4244892185452788977">"Құпия"</string>
<string name="category_clone" msgid="1554511758987195974">"Клондау"</string>
<string name="development_settings_title" msgid="140296922921597393">"Әзірлеуші опциялары"</string>
<string name="development_settings_enable" msgid="4285094651288242183">"Әзірлеуші параметрлерін қосу"</string>
@@ -388,7 +371,7 @@
<string name="media_category" msgid="8122076702526144053">"Mультимeдиа"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Бақылау"</string>
<string name="strict_mode" msgid="889864762140862437">"Қатаң режим қосылған"</string>
- <string name="strict_mode_summary" msgid="1838248687233554654">"Қолданбалар негізгі жолда ұзақ әрекеттерді орындағанда экранды жыпылықтату"</string>
+ <string name="strict_mode_summary" msgid="1838248687233554654">"Қолданбалар ұзақ операцияларды орындағанда экранды жыпылықтату"</string>
<string name="pointer_location" msgid="7516929526199520173">"Меңзер орны"</string>
<string name="pointer_location_summary" msgid="957120116989798464">"Экран бетіне түртілген элемент дерегі көрсетіледі"</string>
<string name="show_touches" msgid="8437666942161289025">"Түрту қимылын көрсету"</string>
@@ -407,7 +390,7 @@
<string name="simulate_color_space" msgid="1206503300335835151">"Түстер кеңістігінің симуляциясы"</string>
<string name="enable_opengl_traces_title" msgid="4638773318659125196">"OpenGL трейстерін қосу"</string>
<string name="usb_audio_disable_routing" msgid="3367656923544254975">"USB-мен аудио жіберуді өшіру"</string>
- <string name="usb_audio_disable_routing_summary" msgid="8768242894849534699">"Сыртқы USB аудио құрылғыларына автоматты жіберуді өшіру"</string>
+ <string name="usb_audio_disable_routing_summary" msgid="8768242894849534699">"Сыртқы USB аудио құрылғыларына автоматты түрде жіберуді өшіру"</string>
<string name="debug_layout" msgid="1659216803043339741">"Жиектерді көрсету"</string>
<string name="debug_layout_summary" msgid="8825829038287321978">"Қию шегін, шеттерді, т.б. көрсету"</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Оңнан солға орналастыру"</string>
@@ -612,7 +595,7 @@
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Сымды аудио құрылғысы"</string>
<string name="help_label" msgid="3528360748637781274">"Анықтама және пікір"</string>
<string name="storage_category" msgid="2287342585424631813">"Жад"</string>
- <string name="shared_data_title" msgid="1017034836800864953">"Бөліскен дерек"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Ортақ дерек"</string>
<string name="shared_data_summary" msgid="5516326713822885652">"Ортақ деректерді көру және өзгерту"</string>
<string name="shared_data_no_blobs_text" msgid="3108114670341737434">"Бұл пайдаланушымен бөліскен дерек жоқ."</string>
<string name="shared_data_query_failure_text" msgid="3489828881998773687">"Ортақ деректер алу кезінде қате шықты. Қайталап көріңіз."</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Орта тек"</string>
<string name="feminine" msgid="1529155595310784757">"Аналық тек"</string>
<string name="masculine" msgid="4653978041013996303">"Аталық тек"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Жүйенің жаңартылған нұсқалары"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 2ba422b..60f88ea 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -721,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"អភេទ"</string>
<string name="feminine" msgid="1529155595310784757">"ស្រី"</string>
<string name="masculine" msgid="4653978041013996303">"ប្រុស"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"បច្ចុប្បន្នភាពប្រព័ន្ធ"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 64facff..6594b5e 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -96,10 +96,8 @@
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"ಸಂಪರ್ಕಗೊಂಡಿದೆ (ಫೋನ್ ಅಥವಾ ಮಾಧ್ಯಮವಿಲ್ಲ), ಬ್ಯಾಟರಿ ಚಾರ್ಜ್ ಮಟ್ಟ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_active_battery_level" msgid="2685517576209066008">"ಸಕ್ರಿಯವಾಗಿದೆ. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ಬ್ಯಾಟರಿ ಮಟ್ಟ."</string>
<string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"ಸಕ್ರಿಯವಾಗಿದೆ. ಎಡ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, ಬಲ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ಬ್ಯಾಟರಿ ಮಟ್ಟ."</string>
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"ಸಕ್ರಿಯವಾಗಿದೆ. ಎಡ: ಬ್ಯಾಟರಿ ಮಟ್ಟ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"ಸಕ್ರಿಯವಾಗಿದೆ. ಬಲ: ಬ್ಯಾಟರಿ ಮಟ್ಟ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ಬ್ಯಾಟರಿ"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ಬ್ಯಾಟರಿ ಇದೆ"</string>
<string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"ಎಡ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, ಬಲ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ಬ್ಯಾಟರಿ ಮಟ್ಟ."</string>
@@ -107,12 +105,9 @@
<string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"ಬಲ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ಬ್ಯಾಟರಿ ಮಟ್ಟ"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"ಸಕ್ರಿಯ"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"ಸೇವ್ ಮಾಡಲಾಗಿದೆ"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"ಸಕ್ರಿಯವಾಗಿದೆ (ಎಡಕಿವಿಯ ಸಾಧನ ಮಾತ್ರ)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"ಸಕ್ರಿಯವಾಗಿದೆ (ಬಲಕಿವಿಯ ಸಾಧನ ಮಾತ್ರ)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"ಸಕ್ರಿಯವಾಗಿವೆ (ಎಡ ಮತ್ತು ಬಲಕಿವಿಯ ಸಾಧನಗಳು)"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"ಸಕ್ರಿಯವಾಗಿದೆ (ಮೀಡಿಯಾ ಮಾತ್ರ). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ಬ್ಯಾಟರಿ ಮಟ್ಟ."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"ಸಕ್ರಿಯವಾಗಿದೆ (ಮೀಡಿಯಾ ಮಾತ್ರ). ಎಡ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, ಬಲ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ಬ್ಯಾಟರಿ ಮಟ್ಟ."</string>
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"ಕನೆಕ್ಟ್ ಆಗಿದೆ (ಆಡಿಯೋ ಹಂಚಿಕೊಳ್ಳುವಿಕೆಯನ್ನು ಬೆಂಬಲಿಸುತ್ತದೆ). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ಬ್ಯಾಟರಿ ಮಟ್ಟ."</string>
@@ -395,7 +390,7 @@
<string name="simulate_color_space" msgid="1206503300335835151">"ಬಣ್ಣದ ಸ್ಥಳ ಸಿಮ್ಯುಲೇಟ್"</string>
<string name="enable_opengl_traces_title" msgid="4638773318659125196">"OpenGL ಕುರುಹುಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
<string name="usb_audio_disable_routing" msgid="3367656923544254975">"USB ಆಡಿಯೋ ರೂಟಿಂಗ್ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ"</string>
- <string name="usb_audio_disable_routing_summary" msgid="8768242894849534699">"USB ಆಡಿಯೋ ಸಲಕರಣೆಗಳಿಗೆ ಸ್ವಯಂ ರೂಟಿಂಗ್ ನಿಷ್ಕ್ರಿಯ."</string>
+ <string name="usb_audio_disable_routing_summary" msgid="8768242894849534699">"USB ಆಡಿಯೋ ಸಲಕರಣೆಗಳಿಗೆ ಸ್ವಯಂಚಾಲಿತ ರೂಟಿಂಗ್ ಅನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ."</string>
<string name="debug_layout" msgid="1659216803043339741">"ಲೇಔಟ್ ಪರಿಮಿತಿಗಳನ್ನು ತೋರಿಸು"</string>
<string name="debug_layout_summary" msgid="8825829038287321978">"ಕ್ಲಿಪ್ನ ಗಡಿಗಳು, ಅಂಚುಗಳು, ಇತ್ಯಾದಿ ತೋರಿಸು."</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"RTL ಲೇಔಟ್ ಡೈರೆಕ್ಷನ್ ಫೋರ್ಸ್ ಮಾಡುವಿಕೆ"</string>
@@ -406,7 +401,7 @@
<string name="force_msaa" msgid="4081288296137775550">"4x MSAA ಫೋರ್ಸ್ ಮಾಡಿ"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"OpenGL ES 2.0 ಅಪ್ಲಿಕೇಶನ್ಗಳಲ್ಲಿ 4x MSAA ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
<string name="show_non_rect_clip" msgid="7499758654867881817">"ಆಯತಾಕಾರವಲ್ಲದ ಕ್ಲಿಪ್ ಕಾರ್ಯಾಚರಣೆ ಡೀಬಗ್"</string>
- <string name="track_frame_time" msgid="522674651937771106">"ಪ್ರೊಫೈಲ್ HWUI ಸಲ್ಲಿಸಲಾಗುತ್ತಿದೆ"</string>
+ <string name="track_frame_time" msgid="522674651937771106">"ಪ್ರೊಫೈಲ್ HWUI ರೆಂಡರಿಂಗ್"</string>
<string name="enable_gpu_debug_layers" msgid="4986675516188740397">"GPU ಡೀಬಗ್ ಲೇಯರ್ಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
<string name="enable_gpu_debug_layers_summary" msgid="4921521407377170481">"ಡೀಬಗ್ ಅಪ್ಲಿಕೇಶನ್ಗಳಿಗಾಗಿ GPU ಡೀಬಗ್ ಲೇಯರ್ಗಳನ್ನು ಲೋಡ್ ಮಾಡುವುದನ್ನು ಅನುಮತಿಸಿ"</string>
<string name="enable_verbose_vendor_logging" msgid="1196698788267682072">"ವರ್ಬೋಸ್ ವೆಂಡರ್ ಲಾಗಿಂಗ್ ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
@@ -726,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"ನಪುಂಸಕ"</string>
<string name="feminine" msgid="1529155595310784757">"ಮಹಿಳೆಯರಿಗಾಗಿ"</string>
<string name="masculine" msgid="4653978041013996303">"ಪುರುಷರಿಗಾಗಿ"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"ಸಿಸ್ಟಂ ಅಪ್ಡೇಟ್ಗಳು"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index b6988ce..d93af73 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"연결됨(전화 없음), 배터리 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"연결됨(미디어 없음), 배터리 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"연결됨(전화 또는 미디어 없음), 배터리 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"사용 중입니다. 배터리는 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>입니다."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"사용 중입니다. 배터리는 왼쪽 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, 오른쪽 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>입니다."</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"활성 상태입니다. 왼쪽: 배터리 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"활성 상태입니다. 오른쪽: 배터리 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"배터리 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"배터리 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"배터리는 왼쪽 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, 오른쪽 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>입니다."</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"왼쪽 배터리는 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>입니다."</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"오른쪽 배터리는 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>입니다."</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"활성"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"저장됨"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"활성(왼쪽만)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"활성(오른쪽만)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"활성(왼쪽 및 오른쪽)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"사용 중입니다(미디어 전용). 배터리는 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>입니다."</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"사용 중입니다(미디어 전용). 배터리는 왼쪽 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, 오른쪽 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>입니다."</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"연결되었습니다(오디오 공유 지원). 배터리는 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>입니다."</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"연결되었습니다(오디오 공유 지원). 배터리는 왼쪽 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, 오른쪽 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>입니다."</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"연결되었습니다(오디오 공유 지원). 왼쪽 배터리는 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>입니다."</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"연결되었습니다(오디오 공유 지원). 오른쪽 배터리는 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>입니다."</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"연결되었습니다(오디오 공유 지원)."</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"사용 중(미디어 전용)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"오디오 공유 지원"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"사용 중(미디어 전용), 왼쪽만"</string>
@@ -304,7 +287,7 @@
<string name="confirm_enable_oem_unlock_text" msgid="854131050791011970">"경고: 이 설정을 사용하는 동안에는 이 기기에서 기기 보호 기능이 작동하지 않습니다."</string>
<string name="mock_location_app" msgid="6269380172542248304">"가상 위치 앱 선택"</string>
<string name="mock_location_app_not_set" msgid="6972032787262831155">"가상 위치 앱이 설정되어 있지 않음"</string>
- <string name="mock_location_app_set" msgid="4706722469342913843">"모의 위치 앱: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="mock_location_app_set" msgid="4706722469342913843">"가상 위치 앱: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="debug_networking_category" msgid="6829757985772659599">"네트워크"</string>
<string name="wifi_display_certification" msgid="1805579519992520381">"무선 디스플레이 인증서"</string>
<string name="wifi_verbose_logging" msgid="1785910450009679371">"Wi-Fi 상세 로깅 사용"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"중성"</string>
<string name="feminine" msgid="1529155595310784757">"여성"</string>
<string name="masculine" msgid="4653978041013996303">"남성"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"시스템 업데이트"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index d084a9bf..4a76d550 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Туташып турат (телефониясыз), батареянын деңгээли – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Туташып турат (медиасыз), батареянын деңгээли – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Туташып турат (телефониясыз же медиасыз), батареянын деңгээли – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Жигердүү. Батарея: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Жигердүү. Батарея: L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Иштеп жатат. Сол: Батареянын кубаты <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Иштеп жатат. Оң: Батареянын кубаты <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Батареянын деңгээли: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Батареянын кубаты: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"Батарея: L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"Сол кулак – батареянын деңгээли: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Оң кулак – батареянын деңгээли: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Жигердүү"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Сакталган"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Иштеп жатат (сол тарап гана)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Иштеп жатат (оң тарап гана)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Иштеп жатат (сол жана оң)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Жигердүү (медиа үчүн гана). Батарея: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Жигердүү (медиа үчүн гана). Батарея: L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Туташкан (чогуу угуу колдоого алынат). Батарея: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Туташкан (чогуу угуу колдоого алынат). Батарея: L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Туташкан (чогуу угуу колдоого алынат). Сол кулак – батареянын деңгээли: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Туташкан (чогуу угуу колдоого алынат). Оң кулак – батареянын деңгээли: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Туташкан (чогуу угуу колдоого алынат)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Активдүү (медиа үчүн гана)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Чогуу угуу колдоого алынат"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Активдүү (медиа үчүн гана), сол кулакчын гана"</string>
@@ -653,7 +636,7 @@
<string name="add_user_failed" msgid="4809887794313944872">"Жаңы колдонуучу түзүлбөй калды"</string>
<string name="add_guest_failed" msgid="8074548434469843443">"Жаңы конок түзүлгөн жок"</string>
<string name="user_nickname" msgid="262624187455825083">"Ылакап аты"</string>
- <string name="edit_user_info_message" msgid="6677556031419002895">"Сиз тандаган аталыш жана сүрөт ушул түзмөктү колдонгондордун баарына көрүнөт."</string>
+ <string name="edit_user_info_message" msgid="6677556031419002895">"Сиз тандаган ысым жана сүрөт ушул түзмөктү колдонгондордун баарына көрүнөт."</string>
<string name="user_add_user" msgid="7876449291500212468">"Колдонуучу кошуу"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Конок кошуу"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Конокту өчүрүү"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Орто жак"</string>
<string name="feminine" msgid="1529155595310784757">"Аял"</string>
<string name="masculine" msgid="4653978041013996303">"Эркек"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Тутум жаңыртуулары"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index cb0c5da..a6040ef 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -371,7 +371,7 @@
<string name="media_category" msgid="8122076702526144053">"ມີເດຍ"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"ກຳລັງກວດສອບ"</string>
<string name="strict_mode" msgid="889864762140862437">"ເປີດໃຊ້ໂໝດເຄັ່ງຄັດ"</string>
- <string name="strict_mode_summary" msgid="1838248687233554654">"ກະພິບໜ້າຈໍເມື່ອມີແອັບ ເຮັດວຽກດົນເກີນໄປໃນເທຣດຫຼັກ"</string>
+ <string name="strict_mode_summary" msgid="1838248687233554654">"ກະພິບໜ້າຈໍເມື່ອມີແອັບເຮັດວຽກດົນເກີນໄປໃນເທຣດຫຼັກ"</string>
<string name="pointer_location" msgid="7516929526199520173">"ຕຳແໜ່ງໂຕຊີ້"</string>
<string name="pointer_location_summary" msgid="957120116989798464">"ການວາງຊ້ອນໜ້າຈໍກຳລັງສະແດງຂໍ້ມູນການສຳຜັດໃນປັດຈຸບັນ"</string>
<string name="show_touches" msgid="8437666942161289025">"ສະແດງການແຕະ"</string>
@@ -721,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"ບໍ່ມີເພດ"</string>
<string name="feminine" msgid="1529155595310784757">"ເພດຍິງ"</string>
<string name="masculine" msgid="4653978041013996303">"ເພດຊາຍ"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"ການອັບເດດລະບົບ"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 0d97309..b84cefb 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -96,10 +96,8 @@
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Prisijungta (<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>), (telefono ar medijos nėra), akumuliatoriaus įkrovos lygis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Aktyvus. Akumuliatorius lygis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Aktyvus. Akumuliatoriaus lygis kairėje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, dešinėje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Aktyvus. K.: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> akumuliatoriaus įkrova."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Aktyvus. D.: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> akumuliatoriaus įkrova."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Akumuliatoriaus įkrova: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Akumuliatorius: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"Akumuliatoriaus lygis kairėje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, dešinėje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
@@ -107,12 +105,9 @@
<string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Akumuliatoriaus lygis dešinėje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktyvus"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Išsaugota"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Aktyvus (tik kairiojoje pusėje)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Aktyvus (tik dešiniojoje pusėje)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Aktyvus (kairiojoje ir dešiniojoje pusėse)"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktyvus (tik medija). Akumuliatorius lygis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktyvus (tik medija), akumuliatoriaus lygis kairėje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, dešinėje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Prijungta (palaikomas garso įrašų bendrinimas). Akumuliatoriaus lygis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
@@ -726,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Bevardė giminė"</string>
<string name="feminine" msgid="1529155595310784757">"Moteriškoji giminė"</string>
<string name="masculine" msgid="4653978041013996303">"Vyriškoji giminė"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Sistemos naujiniai"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index 55fa4d3..c07fae3 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Savienojums izveidots <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (nav tālrunis), akumulatora uzlādes līmenis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Savienojums izveidots (<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>) (nav multivide), akumulatora uzlādes līmenis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Savienojums izveidots (nav tālrunis vai multivide) (<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>), akumulatora uzlādes līmenis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Aktīvs. Akumulatora uzlādes līmenis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Aktīvs. Akumulatora uzlādes līmenis kreisajā austiņā: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, labajā austiņā: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Aktīvs. Kreisā puse: akumulatora uzlādes līmenis ir <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Aktīvs. Labā puse: akumulatora uzlādes līmenis ir <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Akumulatora uzlādes līmenis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Akumulatora uzlādes līmenis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"Akumulatora uzlādes līmenis kreisajā austiņā: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, labajā austiņā: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"Akumulatora uzlādes līmenis kreisajā austiņā: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Akumulatora uzlādes līmenis labajā austiņā: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktīvs"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Saglabāta"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Ierīce aktīva (tikai kreisā auss)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Ierīce aktīva (tikai labā auss)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Ierīces aktīvas (kreisā un labā auss)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktīvs (tikai multividei). Akumulatora uzlādes līmenis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktīvs (tikai multividei). Akumulatora uzlādes līmenis kreisajā austiņā: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, labajā austiņā: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Izveidots savienojums (atbalsta audio kopīgošanu). Akumulatora uzlādes līmenis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Izveidots savienojums (atbalsta audio kopīgošanu). Akumulatora uzlādes līmenis kreisajā austiņā: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, labajā austiņā: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Izveidots savienojums (atbalsta audio kopīgošanu). Akumulatora uzlādes līmenis kreisajā austiņā: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Izveidots savienojums (atbalsta audio kopīgošanu). Akumulatora uzlādes līmenis labajā austiņā: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Izveidots savienojums (atbalsta audio kopīgošanu)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktīvs (tikai multividei)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Atbalsta audio kopīgošanu"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktīvs (tikai multivide), tikai kreisās puses aparāts"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Nekatrā dzimte"</string>
<string name="feminine" msgid="1529155595310784757">"Sieviešu dzimte"</string>
<string name="masculine" msgid="4653978041013996303">"Vīriešu dzimte"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Sistēmas atjauninājumi"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index 6d3d54c..4cd076b 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Поврзан со <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (без телефон), ниво на батеријата <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Поврзан со <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (без аудиовизуелни содржини), ниво на батеријата <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Поврзан со <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (без телефон и аудиовизуелни содржини), ниво на батеријата <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Активно. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батерија."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Активно. Л: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> батерија, Д: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> батерија."</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Активно. Л: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батерија."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Активно. Д: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батерија."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Батерија: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Батерија: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"Л: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> батерија, Д: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> батерија."</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"Лево: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батерија"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Десно: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батерија"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Активен"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Зачувано"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Активно (само лево)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Активно (само десно)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Активно (лево и десно)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Активно (само аудиовизуелни содржини). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батерија."</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Активно (само аудиовизуелни содржини). Л: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> батерија, Д: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> батерија."</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Поврзано (поддржува споделување аудио). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батерија."</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Поврзано (поддржува споделување аудио). Л: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> батерија, Д: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> батерија."</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Поврзано (поддржува споделување аудио). Лево: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батерија."</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Поврзано (поддржува споделување аудио). Десно: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батерија."</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Поврзано (поддржува споделување аудио)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Активно (само аудиовизуелни содржини)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Поддржува споделување аудио"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Активно (само аудиовизуелни содржини), само лево"</string>
@@ -250,7 +233,7 @@
<item msgid="6946761421234586000">"400 %"</item>
</string-array>
<string name="choose_profile" msgid="343803890897657450">"Изберете профил"</string>
- <string name="category_personal" msgid="6236798763159385225">"Лични"</string>
+ <string name="category_personal" msgid="6236798763159385225">"Личен"</string>
<string name="category_work" msgid="4014193632325996115">"Работа"</string>
<string name="category_private" msgid="4244892185452788977">"Приватен"</string>
<string name="category_clone" msgid="1554511758987195974">"Клон"</string>
@@ -388,7 +371,7 @@
<string name="media_category" msgid="8122076702526144053">"Аудиовизуелни содржини"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Следење"</string>
<string name="strict_mode" msgid="889864762140862437">"Овозможен е строг режим"</string>
- <string name="strict_mode_summary" msgid="1838248687233554654">"Осветли екран при долги операции на главна нишка"</string>
+ <string name="strict_mode_summary" msgid="1838248687233554654">"Трепкај со екранот при долги операции на главна нишка"</string>
<string name="pointer_location" msgid="7516929526199520173">"Локација на покажувач"</string>
<string name="pointer_location_summary" msgid="957120116989798464">"Прекривката на екран ги покажува тековните податоци на допир"</string>
<string name="show_touches" msgid="8437666942161289025">"Прикажувај допири"</string>
@@ -653,7 +636,7 @@
<string name="add_user_failed" msgid="4809887794313944872">"Не успеа да создаде нов корисник"</string>
<string name="add_guest_failed" msgid="8074548434469843443">"Не успеа создавањето нов гостин"</string>
<string name="user_nickname" msgid="262624187455825083">"Прекар"</string>
- <string name="edit_user_info_message" msgid="6677556031419002895">"Името и сликата што ќе ги изберете ќе бидат видливи за секој што го користи уредов."</string>
+ <string name="edit_user_info_message" msgid="6677556031419002895">"Името и сликата што ќе ги изберете ќе бидат видливи за секого што го користи уредов."</string>
<string name="user_add_user" msgid="7876449291500212468">"Додајте корисник"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Додајте гостин"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Отстрани гостин"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Среден род"</string>
<string name="feminine" msgid="1529155595310784757">"Женски род"</string>
<string name="masculine" msgid="4653978041013996303">"Машки род"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Системски ажурирања"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 3da1218..5f21c34 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -96,10 +96,8 @@
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"കണക്റ്റ് ചെയ്തു (ഫോണോ മീഡിയയോ ഇല്ല), ബാറ്ററി നില <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_active_battery_level" msgid="2685517576209066008">"സജീവം. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ബാറ്ററി."</string>
<string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"സജീവം. ഇടതുവശത്ത്: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, വലതുവശത്ത്: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ബാറ്ററി."</string>
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"സജീവം. ഇടതുഭാഗത്ത്: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ബാറ്ററി."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"സജീവം. വലതുഭാഗത്ത്: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ബാറ്ററി."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ബാറ്ററി"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"ബാറ്ററി ചാർജ് <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ആണ്"</string>
<string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"ഇടതുവശത്ത്: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, വലതുവശത്ത്: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ബാറ്ററി."</string>
@@ -107,12 +105,9 @@
<string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"വലത് വശത്ത്: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ബാറ്ററി"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"സജീവം"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"സംരക്ഷിച്ചു"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"സജീവമാണ് (ഇടതുഭാഗത്ത് മാത്രം)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"സജീവമാണ് (വലതുഭാഗത്ത് മാത്രം)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"സജീവമാണ് (ഇടതുഭാഗത്തും വലതുഭാഗത്തും)"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"സജീവം (മീഡിയ മാത്രം). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ബാറ്ററി."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"സജീവം (മീഡിയ മാത്രം). ഇടതുവശത്ത്: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> ബാറ്ററി, വലതുവശത്ത്: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ബാറ്ററി."</string>
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"കണക്റ്റ് ചെയ്തു (ഓഡിയോ പങ്കിടൽ പിന്തുണയ്ക്കുന്നു). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ബാറ്ററി."</string>
@@ -726,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"നപുംസകലിംഗം"</string>
<string name="feminine" msgid="1529155595310784757">"സ്ത്രീലിംഗം"</string>
<string name="masculine" msgid="4653978041013996303">"പുല്ലിംഗം"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"സിസ്റ്റം അപ്ഡേറ്റുകൾ"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index c39717c..42797d4 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Холбогдсон (утас байхгүй), батарей <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Холбогдсон (медиа байхгүй), батарей <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Холбогдсон (утас эсвэл медиа байхгүй), батарей <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Идэвхтэй байна. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батарей."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Идэвхтэй байна. З: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Б: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> батарей."</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Идэвхтэй байна. З: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батарей."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Идэвхтэй байна. Б: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батарей."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Батарей <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Батарей <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"З: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Б: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> батарей."</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"Зүүн: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батарей"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Баруун: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батарей."</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Идэвхтэй"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Хадгалсан"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Идэвхтэй (зөвхөн зүүн тал)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Идэвхтэй (зөвхөн баруун тал)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Идэвхтэй (зүүн, баруун тал)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Идэвхтэй (зөвхөн медиа). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батарей."</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Идэвхтэй (зөвхөн медиа). З: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Б: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> батарей."</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Холбогдсон (аудио хуваалцахыг дэмждэг). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батарей."</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Холбогдсон (аудио хуваалцахыг дэмждэг). З: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Б: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> батарей."</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Холбогдсон (аудио хуваалцахыг дэмждэг). Зүүн: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батарей."</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Холбогдсон (аудио хуваалцахыг дэмждэг). Баруун: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батарей."</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Холбогдсон (аудио хуваалцахыг дэмждэг)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Идэвхтэй (зөвхөн медиа)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Аудио хуваалцахыг дэмждэг"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Идэвхтэй (зөвхөн медиа), зөвхөн зүүн"</string>
@@ -406,8 +389,8 @@
<string name="disable_overlays_summary" msgid="1954852414363338166">"Дэлгэц нийлүүлэхэд GPU-г байнга ашиглах"</string>
<string name="simulate_color_space" msgid="1206503300335835151">"Өнгөний орчныг дууриах"</string>
<string name="enable_opengl_traces_title" msgid="4638773318659125196">"OpenGL тэмдэглэлийг идэвхжүүлэх"</string>
- <string name="usb_audio_disable_routing" msgid="3367656923544254975">"USB аудио чиглүүлэхийг идэвхгүйжүүлэх"</string>
- <string name="usb_audio_disable_routing_summary" msgid="8768242894849534699">"USB аудио нэмэлт хэрэгсэл рүү автоматаар чиглүүлэхийг идэвхгүйжүүлэх"</string>
+ <string name="usb_audio_disable_routing" msgid="3367656923544254975">"USB аудио чиглүүлэхийг идэвхгүй болгох"</string>
+ <string name="usb_audio_disable_routing_summary" msgid="8768242894849534699">"USB аудио нэмэлт хэрэгсэл рүү автоматаар чиглүүлэхийг идэвхгүй болгох"</string>
<string name="debug_layout" msgid="1659216803043339741">"Байршлын хүрээг харуулах"</string>
<string name="debug_layout_summary" msgid="8825829038287321978">"Клипийн зах, хязгаар зэргийг харуулах"</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"RTL байрлалын чиглэлийг хүчээр тогтоох"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Саармаг үг"</string>
<string name="feminine" msgid="1529155595310784757">"Эм үг"</string>
<string name="masculine" msgid="4653978041013996303">"Эр үг"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Системийн шинэчлэлт"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 549c784..fecb91f 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -96,10 +96,8 @@
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"कनेक्ट केले (फोन किंवा मीडिया नाही), बॅटरी <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_active_battery_level" msgid="2685517576209066008">"ॲक्टिव्ह आहे. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बॅटरी."</string>
<string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"ॲक्टिव्ह आहे. डावीकडे: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, उजवीकडे: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> बॅटरी."</string>
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"ॲक्टिव्ह आहे. डावीकडे: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बॅटरी."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"ॲक्टिव्ह आहे. उजवीकडे: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बॅटरी."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बॅटरी"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"बॅटरी <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"डावीकडे: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, उजवीकडे: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> बॅटरी."</string>
@@ -107,12 +105,9 @@
<string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"उजवीकडे: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बॅटरी"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"अॅक्टिव्ह"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"सेव्ह केली आहेत"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"अॅक्टिव्ह आहे (फक्त डावे)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"अॅक्टिव्ह आहे (फक्त उजवे)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"अॅक्टिव्ह आहे (डावे आणि उजवे)"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"अॅक्टिव्ह आहे (फक्त मीडिया). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बॅटरी."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"ॲक्टिव्ह आहे (फक्त मीडिया). डावीकडे: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> बॅटरी, उजवीकडे: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> बॅटरी."</string>
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"कनेक्ट केले आहे (ऑडिओ शेअरिंगला सपोर्ट करते). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बॅटरी."</string>
@@ -726,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"नपुसकलिंग"</string>
<string name="feminine" msgid="1529155595310784757">"स्त्रीलिंग"</string>
<string name="masculine" msgid="4653978041013996303">"पुल्लिंग"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"सिस्टीम अपडेट"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index e621643..e8e9e7eb 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -96,10 +96,8 @@
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Disambungkan (tiada telefon atau media), bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Aktif. Bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Aktif. L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: Bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Aktif. L: Bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Aktif. R: Bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: Bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
@@ -107,12 +105,9 @@
<string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Kanan: Bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktif"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Disimpan"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Aktif (kiri sahaja)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Aktif (kanan sahaja)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Aktif (kiri dan kanan)"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktif (media sahaja). Bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktif (media sahaja), L: Bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: Bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Disambungkan (menyokong perkongsian audio). Bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
@@ -240,7 +235,7 @@
<string name="choose_profile" msgid="343803890897657450">"Pilih profil"</string>
<string name="category_personal" msgid="6236798763159385225">"Peribadi"</string>
<string name="category_work" msgid="4014193632325996115">"Tempat Kerja"</string>
- <string name="category_private" msgid="4244892185452788977">"Peribadi"</string>
+ <string name="category_private" msgid="4244892185452788977">"Persendirian"</string>
<string name="category_clone" msgid="1554511758987195974">"Klon"</string>
<string name="development_settings_title" msgid="140296922921597393">"Pilihan pembangun"</string>
<string name="development_settings_enable" msgid="4285094651288242183">"Dayakan pilihan pembangun"</string>
@@ -726,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Neuter"</string>
<string name="feminine" msgid="1529155595310784757">"Feminin"</string>
<string name="masculine" msgid="4653978041013996303">"Maskulin"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Kemaskinian Sistem"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index f4ee284..b3317e4 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -94,39 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"ချိတ်ဆက်ပြီးပြီ (ဖုန်းမရှိပါ)၊ ဘက်ထရီ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"ချိတ်ဆက်ပြီးပြီ (မီဒီယာ မရှိပါ)၊ ဘက်ထရီ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"ချိတ်ဆက်ပြီးပြီ (ဖုန်း (သို့) မီဒီယာ မရှိပါ)၊ ဘက်ထရီ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"အသုံးပြုနေသည်။ ဘက်ထရီ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>။"</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"အသုံးပြုနေသည်။ ဘက်ထရီ L- <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>၊ R- <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>။"</string>
<string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"သုံးနေသည်။ ဘယ်ဘက်- ဘက်ထရီ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>။"</string>
<string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"သုံးနေသည်။ ညာဘက်- ဘက်ထရီ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>။"</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"ဘက်ထရီ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"ဘက်ထရီ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"ဘက်ထရီ L- <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>၊ R- <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>။"</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"ဘယ်- ဘက်ထရီ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"ညာ- ဘက်ထရီ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"ဖွင့်ထားသည်"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"သိမ်းထားသည်များ"</string>
<string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"သုံးနေသည် (ဘယ်ဘက်သီးသန့်)"</string>
<string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"သုံးနေသည် (ညာဘက်သီးသန့်)"</string>
<string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"သုံးနေသည် (ဘယ်နှင့်ညာ)"</string>
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"အသုံးပြုနေသည် (မီဒီယာသီးသန့်)။ ဘက်ထရီ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>။"</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"အသုံးပြုနေသည် (မီဒီယာသီးသန့်)။ ဘက်ထရီ L- <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>၊ R- <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>။"</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"ချိတ်ဆက်ထားသည် (အော်ဒီယို မျှဝေခြင်း ပံ့ပိုးသည်)။ ဘက်ထရီ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>။"</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"ချိတ်ဆက်ထားသည် (အော်ဒီယို မျှဝေခြင်း ပံ့ပိုးသည်)။ ဘက်ထရီ L- <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>၊ R- <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>။"</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"ချိတ်ဆက်ထားသည် (အော်ဒီယို မျှဝေခြင်း ပံ့ပိုးသည်)။ ဘယ်- ဘက်ထရီ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>။"</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"ချိတ်ဆက်ထားသည် (အော်ဒီယို မျှဝေခြင်း ပံ့ပိုးသည်)။ ညာ- ဘက်ထရီ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>။"</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"ချိတ်ဆက်ထားသည် (အော်ဒီယို မျှဝေခြင်း ပံ့ပိုးသည်)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"သုံးနေသည် (မီဒီယာသီးသန့်)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"အော်ဒီယို မျှဝေခြင်း ပံ့ပိုးသည်"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"သုံးနေသည် (မီဒီယာသီးသန့်)၊ ဘယ်သီးသန့်"</string>
@@ -171,7 +159,7 @@
<string name="bluetooth_pairing_decline" msgid="6483118841204885890">"မလုပ်တော့"</string>
<string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"ချိတ်တွဲမှုက ချိတ်ဆက်ထားလျှင် သင်၏ အဆက်အသွယ်များ နှင့် ခေါ်ဆိုမှု မှတ်တမ်းကို ရယူခွင့် ပြုသည်။"</string>
<string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> နှင့် တွဲချိတ်မရပါ"</string>
- <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"ပင်နံပါတ် (သို့) ဖြတ်သန်းခွင့်ကီး မမှန်ကန်သောကြောင့် <xliff:g id="DEVICE_NAME">%1$s</xliff:g> နှင့် တွဲချိတ်၍မရပါ။"</string>
+ <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"ပင်နံပါတ် (သို့) လျှို့ဝှက်ကီး မမှန်ကန်သောကြောင့် <xliff:g id="DEVICE_NAME">%1$s</xliff:g> နှင့် တွဲချိတ်၍မရပါ။"</string>
<string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>နှင့်ဆက်သွယ်မရပါ"</string>
<string name="bluetooth_pairing_rejected_error_message" msgid="5943444352777314442">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>နှင့်တွဲချိတ်ရန် ပယ်ချခံရသည်"</string>
<string name="bluetooth_talkback_computer" msgid="3736623135703893773">"ကွန်ပျူတာ"</string>
@@ -383,7 +371,7 @@
<string name="media_category" msgid="8122076702526144053">"မီဒီယာ"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"စောင့်ကြည့်စစ်ဆေးခြင်း"</string>
<string name="strict_mode" msgid="889864762140862437">"တင်းကြပ်သောစနစ် ဖွင့်ရန်"</string>
- <string name="strict_mode_summary" msgid="1838248687233554654">"အက်ပ်လုပ်ဆောင်မှု ရှည်ကြာလျှင် စကရင်ပြန်စပါ"</string>
+ <string name="strict_mode_summary" msgid="1838248687233554654">"အက်ပ်လုပ်ဆောင်မှု ရှည်ကြာလျှင် စကရင်ပြန်စသည်"</string>
<string name="pointer_location" msgid="7516929526199520173">"မြား၏တည်နေရာ"</string>
<string name="pointer_location_summary" msgid="957120116989798464">"လက်ရှိထိတွေ့မှုဒေတာကို ဖန်သားပေါ်တွင်ထပ်၍ ပြသသည်"</string>
<string name="show_touches" msgid="8437666942161289025">"တို့ခြင်းများကို ပြပါ"</string>
@@ -401,8 +389,8 @@
<string name="disable_overlays_summary" msgid="1954852414363338166">"GPU ကိုမျက်နှာပြင်ခင်းကျင်းရာတွင် အမြဲသုံးပါ။"</string>
<string name="simulate_color_space" msgid="1206503300335835151">"အရောင်စနစ် ပြောင်းရန်"</string>
<string name="enable_opengl_traces_title" msgid="4638773318659125196">"OpenGL ခြေရာခံခြင်းဖွင့်ပါ။"</string>
- <string name="usb_audio_disable_routing" msgid="3367656923544254975">"USB အသံလမ်းကြောင်း ပိတ်ခြင်း"</string>
- <string name="usb_audio_disable_routing_summary" msgid="8768242894849534699">"USB အသံစက်ပစ္စည်းများသို့ အလိုအလျောက် ချိတ်ဆက်ခြင်းကို ပိတ်ရန်"</string>
+ <string name="usb_audio_disable_routing" msgid="3367656923544254975">"USB အသံလမ်းကြောင်း ပိတ်ရန်"</string>
+ <string name="usb_audio_disable_routing_summary" msgid="8768242894849534699">"USB အသံစက်ပစ္စည်းများသို့ အလိုအလျောက် ချိတ်ဆက်ခြင်းကို ပိတ်သည်"</string>
<string name="debug_layout" msgid="1659216803043339741">"ပြကွက်၏ဘောင်များ ပြရန်"</string>
<string name="debug_layout_summary" msgid="8825829038287321978">"ဖြတ်ပိုင်းအနားသတ်များ၊ အနားများ စသဖြင့် ပြပါ။"</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"RTL အပြင်အဆင်အတိုင်း ဖြစ်စေခြင်း"</string>
@@ -733,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"နပုလ္လိင်"</string>
<string name="feminine" msgid="1529155595310784757">"ဣတ္ထိလိင်"</string>
<string name="masculine" msgid="4653978041013996303">"ပုလ္လိင်"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"စနစ်အပ်ဒိတ်များ"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index d7814eb..f1ea63b 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Koblet til (ingen telefon), batteri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Koblet til (ingen medier), batteri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Koblet til (ingen telefon eller medier), batteri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Aktiv. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Aktiv. L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, H: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batteri."</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Aktiv. V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Aktiv. H: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Batteri: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, H: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batteri."</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"Venstre: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Høyre: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktiv"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Lagret"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Aktiv (bare venstre)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Aktiv (bare høyre)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Aktiv (venstre og høyre)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktiv (bare medieinnhold) <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri."</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktiv (bare medieinnhold). V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> batteri, H: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batteri."</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Tilkoblet (støtter lyddeling). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri."</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Tilkoblet (støtter lyddeling). V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> batteri, H: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batteri."</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Tilkoblet (støtter lyddeling). Venstre: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri."</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Tilkoblet (støtter lyddeling). Høyre: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri."</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Tilkoblet (støtter lyddeling)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktiv (bare medieinnhold)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Støtter lyddeling"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktiv (bare medieinnhold), bare venstre"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Intetkjønn"</string>
<string name="feminine" msgid="1529155595310784757">"Hunkjønn"</string>
<string name="masculine" msgid="4653978041013996303">"Hankjønn"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Systemoppdateringer"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index abe48e9..40d604e 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -96,10 +96,8 @@
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"जडान गरियो (फोन वा मिडियाबाहेक), ब्याट्री <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_active_battery_level" msgid="2685517576209066008">"सक्रिय। <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ब्याट्री।"</string>
<string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"सक्रिय। बायाँ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, दायाँ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ब्याट्री।"</string>
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"सक्रिय छ। बायाँ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ब्याट्री।"</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"सक्रिय छ। दायाँ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ब्याट्री।"</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"ब्याट्रीको स्तर: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"ब्याट्री <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"बायाँ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, दायाँ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ब्याट्री।"</string>
@@ -107,12 +105,9 @@
<string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"दायाँ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ब्याट्री"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"सक्रिय"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"सेभ गरिएको"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"सक्रिय छ (बायाँ मात्र)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"सक्रिय छ (दायाँ मात्र)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"सक्रिय छ (दायाँ र बायाँ)"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"सक्रिय छ (मिडिया मात्र)। <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ब्याट्री।"</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"सक्रिय छ (मिडिया मात्र)। बायाँ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, दायाँ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ब्याट्री।"</string>
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"कनेक्ट गरिएको छ (अडियो सेयर गर्न मिल्छ)। <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ब्याट्री।"</string>
@@ -164,7 +159,7 @@
<string name="bluetooth_pairing_decline" msgid="6483118841204885890">"रद्द गर्नुहोस्"</string>
<string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"जब जडान हुन्छ जोडी अनुदानले तपाईँको सम्पर्कहरू पहुँच गर्छ र इतिहास सम्झाउँछ।"</string>
<string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>सँग जोडा मिलाउन सकेन"</string>
- <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"गलत PIN वा पासकीका कारणले <xliff:g id="DEVICE_NAME">%1$s</xliff:g> सँग कनेक्ट गर्न सकिएन।"</string>
+ <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"गलत PIN वा पासकीका कारणले <xliff:g id="DEVICE_NAME">%1$s</xliff:g> मा कनेक्ट गर्न सकिएन।"</string>
<string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> सँग कुराकानी हुन सक्दैन।"</string>
<string name="bluetooth_pairing_rejected_error_message" msgid="5943444352777314442">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> द्वारा जोडा बाँध्ने कार्य अस्वीकृत"</string>
<string name="bluetooth_talkback_computer" msgid="3736623135703893773">"कम्प्युटर"</string>
@@ -726,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"नपुंसक लिङ्ग"</string>
<string name="feminine" msgid="1529155595310784757">"स्त्रीलिङ्ग"</string>
<string name="masculine" msgid="4653978041013996303">"पुलिङ्ग"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"सिस्टम अपडेटहरू"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 3f2e003..00c3acb 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Verbonden: <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (geen telefoon), batterij: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Verbonden: <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (geen media), batterij: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Verbonden: <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (geen telefoon of media), batterij: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Actief. Batterijniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Actief. L: batterijniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: batterijniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Actief. L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batterij."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Actief. R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batterij."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Batterijniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Batterij <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"L: batterijniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: batterijniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"Links: batterijniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Rechts: batterijniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Actief"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Opgeslagen"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Actief (alleen links)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Actief (alleen rechts)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Actief (links en rechts)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Actief (alleen media). Batterijniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Actief (alleen media), L: batterijniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: batterijniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Verbonden (ondersteunt audio delen), batterijniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Verbonden (ondersteunt audio delen), L: batterijniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: batterijniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Verbonden (ondersteunt audio delen). Links: batterijniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Verbonden (ondersteunt audio delen). Rechts: batterijniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Verbonden (ondersteunt audio delen)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Actief (alleen media)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Ondersteunt audio delen"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Actief (alleen media), alleen links"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Onzijdig"</string>
<string name="feminine" msgid="1529155595310784757">"Vrouwelijk"</string>
<string name="masculine" msgid="4653978041013996303">"Mannelijk"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Systeemupdates"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index b233b544..ab150c2 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"ସଂଯୁକ୍ତ ନାହିଁ (ଫୋନ୍ ନୁହେଁ), ବ୍ୟାଟେରୀ<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"ସଂଯୁକ୍ତ ହେଲା (ମିଡିଆ ନୁହେଁ), ବ୍ୟାଟେରୀ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"ସଂଯୁକ୍ତ ହେଲା (ଫୋନ୍ କିମ୍ବା ମେଡିଆ ନୁହେଁ), ବ୍ୟାଟେରୀ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"ସକ୍ରିୟ ଅଛନ୍ତି। <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ବେଟେରୀ।"</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"ସକ୍ରିୟ ଅଛନ୍ତି। ବାମ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, ଡାହାଣ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ବେଟେରୀ।"</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"ସକ୍ରିୟ ଅଛି। ବାମ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ବେଟେରୀ।"</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"ସକ୍ରିୟ ଅଛି। ଡାହାଣ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ବେଟେରୀ।"</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ବେଟେରୀ"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"ବେଟେରୀ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"ବାମ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, ଡାହାଣ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ବେଟେରୀ।"</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"ବାମ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ବେଟେରୀ"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"ଡାହାଣ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ବେଟେରୀ"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"ସକ୍ରିୟ"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"ସେଭ କରାଯାଇଛି"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"ସକ୍ରିୟ (କେବଳ ବାମ)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"ସକ୍ରିୟ (କେବଳ ଡାହାଣ)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"ସକ୍ରିୟ (ବାମ ଏବଂ ଡାହାଣ)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"ସକ୍ରିୟ (କେବଳ ମିଡିଆ)। <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ବେଟେରୀ।"</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"ସକ୍ରିୟ (କେବଳ ମିଡିଆ)। ବାମ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, ଡାହାଣ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ବେଟେରୀ।"</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"କନେକ୍ଟ କରାଯାଇଛି (ଅଡିଓ ସେୟାରିଂକୁ ସମର୍ଥନ କରେ)। <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ବେଟେରୀ।"</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"କନେକ୍ଟ କରାଯାଇଛି (ଅଡିଓ ସେୟାରିଂକୁ ସମର୍ଥନ କରେ)। ବାମ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, ଡାହାଣ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ବେଟେରୀ।"</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"କନେକ୍ଟ କରାଯାଇଛି (ଅଡିଓ ସେୟାରିଂକୁ ସମର୍ଥନ କରେ)। ବାମ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ବେଟେରୀ।"</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"କନେକ୍ଟ କରାଯାଇଛି (ଅଡିଓ ସେୟାରିଂକୁ ସମର୍ଥନ କରେ)। ଡାହାଣ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ବେଟେରୀ।"</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"କନେକ୍ଟ କରାଯାଇଛି (ଅଡିଓ ସେୟାରିଂକୁ ସମର୍ଥନ କରେ)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"ସକ୍ରିୟ (କେବଳ ମିଡିଆ)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"ଅଡିଓ ସେୟାରିଂକୁ ସମର୍ଥନ କରେ"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"ସକ୍ରିୟ (କେବଳ ମିଡିଆ), କେବଳ ବାମ"</string>
@@ -249,7 +232,7 @@
<item msgid="4446831566506165093">"350%"</item>
<item msgid="6946761421234586000">"400%"</item>
</string-array>
- <string name="choose_profile" msgid="343803890897657450">"ପ୍ରୋଫାଇଲ୍ ବାଛନ୍ତୁ"</string>
+ <string name="choose_profile" msgid="343803890897657450">"ପ୍ରୋଫାଇଲ ବାଛନ୍ତୁ"</string>
<string name="category_personal" msgid="6236798763159385225">"ବ୍ୟକ୍ତିଗତ"</string>
<string name="category_work" msgid="4014193632325996115">"ୱାର୍କ"</string>
<string name="category_private" msgid="4244892185452788977">"ପ୍ରାଇଭେଟ"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"ନ୍ୟୁଟର"</string>
<string name="feminine" msgid="1529155595310784757">"ସ୍ତ୍ରୀଲିଙ୍ଗ"</string>
<string name="masculine" msgid="4653978041013996303">"ପୁଲିଙ୍ଗ"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"ସିଷ୍ଟମ ଅପଡେଟଗୁଡ଼ିକ"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index 73fe924..0e77a04 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"ਕਨੈਕਟ ਕੀਤਾ ਹੋਇਆ (ਕੋਈ ਫ਼ੋਨ ਨਹੀਂ), ਬੈਟਰੀ ਦਾ ਪੱਧਰ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"ਕਨੈਕਟ ਕੀਤਾ ਹੋਇਆ (ਕੋਈ ਮੀਡੀਆ ਨਹੀਂ), ਬੈਟਰੀ ਦਾ ਪੱਧਰ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"ਕਨੈਕਟ ਕੀਤਾ ਹੋਇਆ (ਕੋਈ ਫ਼ੋਨ ਜਾਂ ਮੀਡੀਆ ਨਹੀਂ), ਬੈਟਰੀ ਦਾ ਪੱਧਰ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"ਕਿਰਿਆਸ਼ੀਲ। <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ਬੈਟਰੀ।"</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"ਕਿਰਿਆਸ਼ੀਲ। ਖੱਬੇ ਪਾਸੇ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, ਸੱਜੇ ਪਾਸੇ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ਬੈਟਰੀ।"</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"ਕਿਰਿਆਸ਼ੀਲ। ਖੱਬਾ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ਬੈਟਰੀ।"</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"ਕਿਰਿਆਸ਼ੀਲ। ਸੱਜਾ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ਬੈਟਰੀ।"</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ਬੈਟਰੀ"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"ਬੈਟਰੀ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"ਖੱਬੇ ਪਾਸੇ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, ਸੱਜੇ ਪਾਸੇ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ਬੈਟਰੀ।"</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"ਖੱਬੇ ਪਾਸੇ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ਬੈਟਰੀ"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"ਸੱਜੇ ਪਾਸੇ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ਬੈਟਰੀ"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"ਕਿਰਿਆਸ਼ੀਲ"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"ਰੱਖਿਅਤ ਕੀਤਾ ਗਿਆ"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"ਕਿਰਿਆਸ਼ੀਲ (ਸਿਰਫ਼ ਖੱਬਾ)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"ਕਿਰਿਆਸ਼ੀਲ (ਸਿਰਫ਼ ਸੱਜਾ)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"ਕਿਰਿਆਸ਼ੀਲ (ਖੱਬਾ ਅਤੇ ਸੱਜਾ)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"ਕਿਰਿਆਸ਼ੀਲ (ਸਿਰਫ਼ ਮੀਡੀਆ)। <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ਬੈਟਰੀ।"</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"ਕਿਰਿਆਸ਼ੀਲ (ਸਿਰਫ਼ ਮੀਡੀਆ)। ਖੱਬੇ ਪਾਸੇ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, ਸੱਜੇ ਪਾਸੇ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ਬੈਟਰੀ।"</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"ਕਨੈਕਟ ਕੀਤਾ (ਆਡੀਓ ਸਾਂਝਾਕਰਨ ਦਾ ਸਮਰਥਨ ਕਰਦਾ ਹੈ)। <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ਬੈਟਰੀ।"</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"ਕਨੈਕਟ ਕੀਤਾ (ਆਡੀਓ ਸਾਂਝਾਕਰਨ ਦਾ ਸਮਰਥਨ ਕਰਦਾ ਹੈ)। ਖੱਬੇ ਪਾਸੇ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, ਸੱਜੇ ਪਾਸੇ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ਬੈਟਰੀ।"</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"ਕਨੈਕਟ ਕੀਤਾ (ਆਡੀਓ ਸਾਂਝਾਕਰਨ ਦਾ ਸਮਰਥਨ ਕਰਦਾ ਹੈ)। ਖੱਬੇ ਪਾਸੇ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ਬੈਟਰੀ।"</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"ਕਨੈਕਟ ਕੀਤਾ (ਆਡੀਓ ਸਾਂਝਾਕਰਨ ਦਾ ਸਮਰਥਨ ਕਰਦਾ ਹੈ)। ਸੱਜੇ ਪਾਸੇ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ਬੈਟਰੀ।"</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"ਕਨੈਕਟ ਕੀਤਾ (ਆਡੀਓ ਸਾਂਝਾਕਰਨ ਦਾ ਸਮਰਥਨ ਕਰਦਾ ਹੈ)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"ਕਿਰਿਆਸ਼ੀਲ (ਸਿਰਫ਼ ਮੀਡੀਆ)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"ਆਡੀਓ ਸਾਂਝਾਕਰਨ ਦਾ ਸਮਰਥਨ ਕਰਦਾ ਹੈ"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"ਕਿਰਿਆਸ਼ੀਲ (ਸਿਰਫ਼ ਮੀਡੀਆ), ਸਿਰਫ਼ ਖੱਬਾ"</string>
@@ -252,7 +235,7 @@
<string name="choose_profile" msgid="343803890897657450">"ਪ੍ਰੋਫਾਈਲ ਚੁਣੋ"</string>
<string name="category_personal" msgid="6236798763159385225">"ਨਿੱਜੀ"</string>
<string name="category_work" msgid="4014193632325996115">"ਕੰਮ ਸੰਬੰਧੀ"</string>
- <string name="category_private" msgid="4244892185452788977">"ਨਿੱਜੀ"</string>
+ <string name="category_private" msgid="4244892185452788977">"ਪ੍ਰਾਈਵੇਟ"</string>
<string name="category_clone" msgid="1554511758987195974">"ਕਲੋਨ ਕਰੋ"</string>
<string name="development_settings_title" msgid="140296922921597393">"ਵਿਕਾਸਕਾਰ ਚੋਣਾਂ"</string>
<string name="development_settings_enable" msgid="4285094651288242183">"ਵਿਕਾਸਕਾਰ ਵਿਕਲਪਾਂ ਨੂੰ ਚਾਲੂ ਕਰੋ"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"ਨਿਰਪੱਖ"</string>
<string name="feminine" msgid="1529155595310784757">"ਇਸਤਰੀ-ਲਿੰਗ"</string>
<string name="masculine" msgid="4653978041013996303">"ਪੁਲਿੰਗ"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"ਸਿਸਟਮ ਅੱਪਡੇਟ"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 6907102..0906d4b 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -95,28 +95,23 @@
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Połączono (bez multimediów), bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> – <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Połączono (bez telefonu i multimediów), bateria <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> – <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Aktywne. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> naładowania baterii."</string>
- <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Aktywne. Lewa: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> naładowania baterii, prawa: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> naładowania baterii."</string>
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Aktywne. Lewa: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, prawa: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> naładowania baterii."</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Aktywne. L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterii."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Aktywne. P: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterii."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> naładowania baterii"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Bateria <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"Lewa: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> naładowania baterii, prawa: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> naładowania baterii."</string>
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"Lewa: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, prawa: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> naładowania baterii."</string>
<string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"Lewa: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> naładowania baterii"</string>
<string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Prawa: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> naładowania baterii"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Urządzenie aktywne"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Zapisano"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Aktywne (tylko lewa strona)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Aktywne (tylko prawa strona)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Aktywne (lewa i prawa strona)"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktywne (tylko multimedia). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> naładowania baterii."</string>
- <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktywne (tylko multimedia), lewa: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> baterii, prawa: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> naładowania baterii."</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktywne (tylko multimedia), lewa: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, prawa: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> naładowania baterii."</string>
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Połączone (obsługa udostępniania dźwięku), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> naładowania baterii."</string>
- <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Połączone (obsługa udostępniania dźwięku), lewa: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> naładowania baterii, prawa: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> naładowania baterii."</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Połączone (obsługa udostępniania dźwięku), lewa: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, prawa: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> naładowania baterii."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Połączone (obsługa udostępniania dźwięku). Lewa: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> naładowania baterii."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Połączone (obsługa udostępniania dźwięku). Prawa: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> naładowania baterii."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Połączone (obsługa udostępniania dźwięku)"</string>
@@ -726,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Nijaki"</string>
<string name="feminine" msgid="1529155595310784757">"Żeński"</string>
<string name="masculine" msgid="4653978041013996303">"Męski"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Aktualizacje systemu"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 5bc01f1..422d0f2 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Conectado (sem telefone), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> de bateria"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Conectado (sem mídia), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> de bateria"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Conectado (sem telefone ou mídia), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> de bateria"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Ativo. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Ativo. Lado esquerdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de bateria. Lado direito: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de bateria."</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Ativo. Lado esquerdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Ativo. Lado direito: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"Lado esquerdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de bateria. Lado direito: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de bateria."</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"Lado esquerdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Lado direito: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Ativo"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Salvo"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Ativo (apenas o esquerdo)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Ativo (apenas o direito)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Ativo (esquerdo e direito)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Ativo (apenas mídia). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria."</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Ativo (apenas mídia). Lado esquerdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de bateria. Lado direito: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de bateria."</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Conectado (com suporte ao compartilhamento de áudio). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria."</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Conectado (com suporte ao compartilhamento de áudio). Lado esquerdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de bateria. Lado direito: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de bateria."</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Conectado (com suporte ao compartilhamento de áudio). Lado esquerdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria."</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Conectado (com suporte ao compartilhamento de áudio). Lado direito: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria."</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Conectado (com suporte ao compartilhamento de áudio)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Ativo (apenas mídia)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Com suporte ao compartilhamento de áudio"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Ativo (apenas mídia), apenas esquerdo"</string>
@@ -592,7 +575,7 @@
<string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Alto-falante da base"</string>
<string name="media_transfer_external_device_name" msgid="2588672258721846418">"Dispositivo externo"</string>
<string name="media_transfer_default_device_name" msgid="4315604017399871828">"Dispositivo conectado"</string>
- <string name="media_transfer_this_phone" msgid="7194341457812151531">"Este telefone"</string>
+ <string name="media_transfer_this_phone" msgid="7194341457812151531">"Neste telefone"</string>
<string name="media_output_status_unknown_error" msgid="5098565887497902222">"Não é possível reproduzir neste dispositivo"</string>
<string name="media_output_status_require_premium" msgid="8411255800047014822">"Faça upgrade da conta para trocar"</string>
<string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Não é possível abrir os downloads aqui"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Neutro"</string>
<string name="feminine" msgid="1529155595310784757">"Feminino"</string>
<string name="masculine" msgid="4653978041013996303">"Masculino"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Atualizações do sistema"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 671c9f7..0bcca15 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -94,39 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Ligado (sem telemóvel), bateria a <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Ligado (sem multimédia), bateria a <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Ligado (sem telemóvel nem multimédia), bateria a <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Ativo. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Ativo. E: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>. D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de bateria."</string>
<string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Ativo. E: bateria a <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Ativo. D: bateria a <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Bateria. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"E: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>. D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de bateria."</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"Esquerdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Direito: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Ativo"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Guardado"</string>
<string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Ativo (apenas esquerdo)"</string>
<string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Ativo (apenas direito)"</string>
<string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Ativo (esquerdo e direito)"</string>
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Ativo (apenas para multimédia). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria."</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Ativo (apenas para multimédia). E: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de bateria. D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de bateria."</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Ligado (suporta partilha de áudio). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria."</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Ligado (suporta partilha de áudio). E: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de bateria. D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de bateria."</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Ligado (suporta a partilha de áudio). Esquerdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria."</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Ligado (suporta a partilha de áudio). Direito: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria."</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Ligado (suporta a partilha de áudio)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Ativo (apenas para multimédia)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Suporta partilha de áudio"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Ativo (apenas para multimédia), apenas esquerdo"</string>
@@ -244,7 +232,7 @@
<item msgid="4446831566506165093">"350%"</item>
<item msgid="6946761421234586000">"400%"</item>
</string-array>
- <string name="choose_profile" msgid="343803890897657450">"Escolher perfil"</string>
+ <string name="choose_profile" msgid="343803890897657450">"Escolha o perfil"</string>
<string name="category_personal" msgid="6236798763159385225">"Pessoal"</string>
<string name="category_work" msgid="4014193632325996115">"Trabalho"</string>
<string name="category_private" msgid="4244892185452788977">"Privado"</string>
@@ -733,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Neutro"</string>
<string name="feminine" msgid="1529155595310784757">"Feminino"</string>
<string name="masculine" msgid="4653978041013996303">"Masculino"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Atualizações do sistema"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 5bc01f1..422d0f2 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Conectado (sem telefone), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> de bateria"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Conectado (sem mídia), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> de bateria"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Conectado (sem telefone ou mídia), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> de bateria"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Ativo. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Ativo. Lado esquerdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de bateria. Lado direito: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de bateria."</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Ativo. Lado esquerdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Ativo. Lado direito: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"Lado esquerdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de bateria. Lado direito: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de bateria."</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"Lado esquerdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Lado direito: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Ativo"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Salvo"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Ativo (apenas o esquerdo)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Ativo (apenas o direito)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Ativo (esquerdo e direito)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Ativo (apenas mídia). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria."</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Ativo (apenas mídia). Lado esquerdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de bateria. Lado direito: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de bateria."</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Conectado (com suporte ao compartilhamento de áudio). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria."</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Conectado (com suporte ao compartilhamento de áudio). Lado esquerdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de bateria. Lado direito: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de bateria."</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Conectado (com suporte ao compartilhamento de áudio). Lado esquerdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria."</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Conectado (com suporte ao compartilhamento de áudio). Lado direito: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria."</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Conectado (com suporte ao compartilhamento de áudio)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Ativo (apenas mídia)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Com suporte ao compartilhamento de áudio"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Ativo (apenas mídia), apenas esquerdo"</string>
@@ -592,7 +575,7 @@
<string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Alto-falante da base"</string>
<string name="media_transfer_external_device_name" msgid="2588672258721846418">"Dispositivo externo"</string>
<string name="media_transfer_default_device_name" msgid="4315604017399871828">"Dispositivo conectado"</string>
- <string name="media_transfer_this_phone" msgid="7194341457812151531">"Este telefone"</string>
+ <string name="media_transfer_this_phone" msgid="7194341457812151531">"Neste telefone"</string>
<string name="media_output_status_unknown_error" msgid="5098565887497902222">"Não é possível reproduzir neste dispositivo"</string>
<string name="media_output_status_require_premium" msgid="8411255800047014822">"Faça upgrade da conta para trocar"</string>
<string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Não é possível abrir os downloads aqui"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Neutro"</string>
<string name="feminine" msgid="1529155595310784757">"Feminino"</string>
<string name="masculine" msgid="4653978041013996303">"Masculino"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Atualizações do sistema"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 4d6638a..ea97c37 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Conectat (fără telefon), baterie <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Conectat (fără conținut media), baterie <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Conectat (fără telefon sau conținut media), baterie <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Activ. Nivelul bateriei <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Activ. Nivelul bateriei din stânga: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, dreapta: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Activ. Nivelul bateriei din stânga: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Activ. Nivelul bateriei din dreapta: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Nivelul bateriei: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Baterie: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"Nivelul bateriei din stânga: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, dreapta: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"Nivelul bateriei din stânga: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Nivelul bateriei din dreapta:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Activ"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Salvat"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Activ (numai stânga)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Activ (numai dreapta)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Activ (stânga și dreapta)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Activ (numai pentru conținut media). Nivelul bateriei <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Activ (numai pentru conținut media): nivelul bateriei din stânga: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, nivelul bateriei din dreapta: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Conectat (acceptă permiterea accesului la audio). Nivelul bateriei: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Conectat (acceptă permiterea accesului la audio), nivelul bateriei din stânga: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, nivelul bateriei din dreapta: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Conectat (acceptă permiterea accesului la audio). Nivelul bateriei din stânga: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Conectat (acceptă permiterea accesului la audio). Nivelul bateriei din dreapta: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Conectat (acceptă permiterea accesului la audio)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Activ (numai pentru conținut media)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Acceptă permiterea accesului la audio"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Activ (numai pentru conținut media), numai stânga"</string>
@@ -406,7 +389,7 @@
<string name="disable_overlays_summary" msgid="1954852414363338166">"Folosește mereu GPU pentru compunerea ecranului"</string>
<string name="simulate_color_space" msgid="1206503300335835151">"Simulează spațiu culoare"</string>
<string name="enable_opengl_traces_title" msgid="4638773318659125196">"Monitorizări OpenGL"</string>
- <string name="usb_audio_disable_routing" msgid="3367656923544254975">"Dezactivați rutarea audio USB"</string>
+ <string name="usb_audio_disable_routing" msgid="3367656923544254975">"Dezactivează rutarea audio USB"</string>
<string name="usb_audio_disable_routing_summary" msgid="8768242894849534699">"Dezact. rutarea automată către perif. audio USB"</string>
<string name="debug_layout" msgid="1659216803043339741">"Afișează limite aspect"</string>
<string name="debug_layout_summary" msgid="8825829038287321978">"Afișează limitele clipului, marginile etc."</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Neutru"</string>
<string name="feminine" msgid="1529155595310784757">"Feminin"</string>
<string name="masculine" msgid="4653978041013996303">"Masculin"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Actualizări de sistem"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index e155948..54c9b0a 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -94,47 +94,30 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Подключено (кроме звонков), уровень заряда батареи: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Подключено (кроме аудио), уровень заряда батареи: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Подключено (кроме звонков и аудио), уровень заряда батареи: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Используется, заряд: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Используется, заряд: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> (Л), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> (П)."</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Используется, заряд: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> (Л)"</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Используется, заряд: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> (П)"</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Уровень заряда: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Батарея <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"Заряд: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> (Л), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> (П)."</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"Заряд: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> (Л)"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Заряд: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> (П)"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Активно"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Сохранено"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Используется (только левый)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Используется (только правый)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Используется (левый и правый)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Используется (только для медиа), заряд: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Используется (только для медиа), заряд: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> (Л), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> (П)."</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Подключено (поддерживается отправка аудио), заряд: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Подключено (поддерживается отправка аудио), заряд: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> (Л), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> (П)."</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Подключено (поддерживается отправка аудио), заряд: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> (Л)."</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Подключено (поддерживается отправка аудио), заряд: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> (П)."</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Подключено (поддерживается отправка аудио)."</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Используется (только для медиа)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Поддерживается отправка аудио"</string>
- <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Используется (только для медиа), левый наушник"</string>
+ <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Используется (только для медиа), только левый"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Используется (только для медиа), правый наушник"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Используется (только для медиа), левый и правый наушники"</string>
<string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Профиль A2DP"</string>
@@ -176,7 +159,7 @@
<string name="bluetooth_pairing_decline" msgid="6483118841204885890">"Отмена"</string>
<string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"Установление соединения обеспечивает доступ к вашим контактам и журналу звонков при подключении."</string>
<string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"Не удалось подключиться к устройству \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\"."</string>
- <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"\"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\" не подключается: неверный PIN-код или пароль."</string>
+ <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Устройство \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\" не подключено: неверный PIN-код или пароль."</string>
<string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"Не удается установить соединение с устройством \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\"."</string>
<string name="bluetooth_pairing_rejected_error_message" msgid="5943444352777314442">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> не разрешает подключение."</string>
<string name="bluetooth_talkback_computer" msgid="3736623135703893773">"Компьютер"</string>
@@ -252,7 +235,7 @@
<string name="choose_profile" msgid="343803890897657450">"Выбор профиля"</string>
<string name="category_personal" msgid="6236798763159385225">"Личный профиль"</string>
<string name="category_work" msgid="4014193632325996115">"Рабочий профиль"</string>
- <string name="category_private" msgid="4244892185452788977">"Личный профиль"</string>
+ <string name="category_private" msgid="4244892185452788977">"Частный профиль"</string>
<string name="category_clone" msgid="1554511758987195974">"Клон"</string>
<string name="development_settings_title" msgid="140296922921597393">"Для разработчиков"</string>
<string name="development_settings_enable" msgid="4285094651288242183">"Включить параметры для разработчиков"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Средний"</string>
<string name="feminine" msgid="1529155595310784757">"Женский"</string>
<string name="masculine" msgid="4653978041013996303">"Мужской"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Обновления системы"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index 0c494e4..ab423b5 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -96,10 +96,8 @@
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"සම්බන්ධිතයි (දුරකථනය හෝ මාධ්ය නැත), බැටරිය <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_active_battery_level" msgid="2685517576209066008">"ක්රියාත්මකයි. බැටරිය <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"ක්රියාත්මකයි. බැටරිය ව: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, ද: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"ක්රියාත්මකයි. ව: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> බැටරිය."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"ක්රියාත්මකයි. ද: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> බැටරිය."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"බැටරිය <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"බැටරිය <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"බැටරිය ව: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, ද: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
@@ -107,12 +105,9 @@
<string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"දකුණ: බැටරිය <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"ක්රියාකාරී"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"සුරැකිණි"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"සක්රිය (වම පමණි)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"සක්රිය (දකුණ පමණි)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"සක්රිය (වම සහ දකුණ)"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"ක්රියාත්මකයි (මාධ්ය පමණයි). බැටරිය <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"ක්රියාත්මකයි (මාධ්ය පමණයි), බැටරිය ව: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, ද: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"සම්බන්ධයි (ශ්රව්ය බෙදා ගැනීමට සහය දක්වයි). බැටරිය <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
@@ -726,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"නපුංසක"</string>
<string name="feminine" msgid="1529155595310784757">"ස්ත්රී"</string>
<string name="masculine" msgid="4653978041013996303">"පුරුෂ"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"පද්ධති යාවත්කාලීන"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index fe41beb..7922b70 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -96,10 +96,8 @@
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Pripojené k zariadeniu <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (bez telefónu a médií), úroveň batérie <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Aktívne. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batérie."</string>
<string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Aktívne. Ľ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, P: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batérie."</string>
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Aktívne. Ľ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batérie."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Aktívne. P: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batérie."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Batéria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Batéria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"Ľ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, P: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batérie."</string>
@@ -107,12 +105,9 @@
<string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Pravá strana: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batérie"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktívne"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Uložené"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Aktívne (iba ľavé)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Aktívne (iba pravé)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Aktívne (ľavé aj pravé)"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktívne (iba médiá). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batérie."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktívne (iba médiá). Ľ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> batérie, P: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batérie."</string>
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Pripojené (podporuje zdieľanie zvuku). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batérie."</string>
@@ -726,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Stredný rod"</string>
<string name="feminine" msgid="1529155595310784757">"Ženský rod"</string>
<string name="masculine" msgid="4653978041013996303">"Mužský rod"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Aktualizácie systému"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 32b6d21..d412f57 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -96,10 +96,8 @@
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Povezano (brez telefona ali predstavnosti), raven napolnjenosti baterije je <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Aktivno. Baterija: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Aktivno. Baterija – L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Aktivno. Baterija – L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Aktivno. Baterija – D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Baterija na <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Baterija: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"Baterija – L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
@@ -107,12 +105,9 @@
<string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Desno – baterija: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktivna"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Shranjeno"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Aktivno (samo levo)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Aktivno (samo desno)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Aktivno (levo in desno)"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktivno (samo predstavnost). Baterija: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktivno (samo predstavnost), baterija – L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Povezano (podpira deljenje zvoka), baterija: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -373,7 +368,7 @@
<string name="debug_input_category" msgid="7349460906970849771">"Vnos"</string>
<string name="debug_drawing_category" msgid="5066171112313666619">"Risanje"</string>
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Upodabljanje s strojnim pospeševanjem"</string>
- <string name="media_category" msgid="8122076702526144053">"Predstavnosti"</string>
+ <string name="media_category" msgid="8122076702526144053">"Predstavnost"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Spremljanje"</string>
<string name="strict_mode" msgid="889864762140862437">"Strog način je omogočen"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Osveži zaslon pri dolgih postopkih v glavni niti."</string>
@@ -726,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Srednji spol"</string>
<string name="feminine" msgid="1529155595310784757">"Ženski spol"</string>
<string name="masculine" msgid="4653978041013996303">"Moški spol"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Posodobitve sistema"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index f112060..944d992 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"E lidhur (pa telefon), bateria <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"E lidhur (pa media), bateria <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"E lidhur (pa telefon ose media), bateria <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Aktiv. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> bateri."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Aktiv. Majtas: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> bateri, djathtas: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> bateri."</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Aktive. Majtas: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> (niveli i baterisë)."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Aktive. Djathtas: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> (niveli i baterisë)."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Bateria <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> bateri"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"Majtas: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> bateri, djathtas: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> bateri."</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"Majtas: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> bateri"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Djathtas: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> bateri"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktiv"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Të ruajtura"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Aktive (vetëm majtas)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Aktive (vetëm djathtas)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Aktive (majtas dhe djathtas)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktiv (vetëm për media). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> bateri."</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktiv (vetëm për media). Majtas: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> bateri, djathtas: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> bateri."</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Lidhur (mbështet ndarjen e audios). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> bateri."</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Lidhur (mbështet ndarjen e audios). Majtas: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> bateri, djathtas: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> bateri."</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Lidhur (mbështet ndarjen e audios). Majtas: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> bateri."</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Lidhur (mbështet ndarjen e audios). Djathtas: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> bateri."</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Lidhur (mbështet ndarjen e audios)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktiv (vetëm për media)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Mbështet ndarjen e audios"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktiv (vetëm për media), vetëm majtas"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Asnjanëse"</string>
<string name="feminine" msgid="1529155595310784757">"Femërore"</string>
<string name="masculine" msgid="4653978041013996303">"Mashkullore"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Përditësimet e sistemit"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 9341616..1bb801d 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Повезано (без телефона), ниво батерије је <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Повезано (без медија), ниво батерије је <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Повезано (без телефона или медија), ниво батерије је <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Активно. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батерије."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Активно. Лево: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, десно: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> батерије."</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Активно. Лево: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батерије."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Активно. Десно: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батерије."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Ниво батерије је <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Батерија, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"Лево: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, десно: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> батерије."</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"Лево: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батерије"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Десно: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батерије"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Активан"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Сачувано"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Активно (само лево)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Активно (само десно)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Активно (лево и десно)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Активно (само за медије). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батерије."</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Активно (само за медије). Лево: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, десно: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> батерије."</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Повезано (подржава дељење звука), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батерије."</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Повезано (подржава дељење звука), лево: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, десно: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> батерије."</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Повезано (подржава дељење звука). Лево: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батерије"</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Повезано (подржава дељење звука). Десно: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батерије."</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Повезано (подржава дељење звука)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Активан (само за медије)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Подржава дељење звука"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Активан (само за медије), само лево"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Средњи род"</string>
<string name="feminine" msgid="1529155595310784757">"Женски род"</string>
<string name="masculine" msgid="4653978041013996303">"Мушки род"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Ажурирања система."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index d3370e8..cc32432 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Ansluten (ingen mobil), batterinivå <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Ansluten (inga medier), batterinivå <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Ansluten (ingen mobil och inga medier), batterinivå <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Aktiv. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Aktiv. V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, H: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batteri."</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Aktiv. V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Aktiv. H: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Batteri: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, H: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batteri."</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"Vänster: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Höger: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktiv"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Sparad"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Aktiv (endast vänster)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Aktiv (endast höger)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Aktiv (vänster och höger)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktiv (endast media). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri."</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktiv (endast media). V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, H: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batteri."</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Ansluten (ljuddelning stöds). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri."</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Ansluten (ljuddelning stöds). V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, H: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batteri."</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Ansluten (ljuddelning stöds). Vänster: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri."</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Ansluten (ljuddelning stöds). Höger: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri."</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Ansluten (ljuddelning stöds)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktiv (endast media)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Ljuddelning stöds"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktiv (endast media), endast vänster"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Neutrum"</string>
<string name="feminine" msgid="1529155595310784757">"Femininformer"</string>
<string name="masculine" msgid="4653978041013996303">"Maskulinformer"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Systemuppdateringar"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index f1d2207..0eac15c 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -94,39 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Imeunganishwa (hamna simu), kiasi cha chaji ni <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Imeunganishwa (hamna kifaa cha sauti), kiasi cha chaji ni <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Imeunganishwa (hamna simu au kifaa cha sauti), kiasi cha chaji ni <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Inatumika. Chaji ya betri imefika <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Inatumika. Kushoto: chaji ya betri imefika <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Kulia: chaji ya betri imefika <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
<string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Inatumika. Kushoto: chaji ya betri imefika <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Inatumika. Kulia: chaji ya betri imefika <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Chaji ya betri ni <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Chaji ya betri ni <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"Kushoto: chaji ya betri imefika <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Kulia: chaji ya betri imefika <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"Kushoto: chaji ya betri imefika <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Kulia: chaji ya betri imefika <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Kimeunganishwa"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Imeokoa"</string>
<string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Inatumika (kushoto pekee)"</string>
<string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Inatumika (kulia pekee)"</string>
<string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Inatumika (kushoto na kulia)"</string>
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Inatumika (maudhui pekee). Chaji ya betri imefika <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Inatumika (maudhui pekee), Kushoto: chaji ya betri imefika <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Kulia: chaji ya betri imefika <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Imeunganishwa (inaweza kutumia kipengele cha kusikiliza pamoja). Chaji ya betri imefika <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Imeunganishwa (inaweza kutumia kipengele cha kusikiliza pamoja). Kushoto: chaji ya betri imefika <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Kulia: chaji ya betri imefika <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Imeunganishwa (inaweza kutumia kipengele cha kusikiliza pamoja). Kushoto: chaji ya betri imefika <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Imeunganishwa (inaweza kutumia kipengele cha kusikiliza pamoja). Kulia: chaji ya betri imefika <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Imeunganishwa (inaweza kutumia kipengele cha kusikiliza pamoja)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Inatumika (maudhui pekee)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Inaweza kutumia kipengele cha kusikiliza pamoja"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Inatumika (maudhui pekee), kushoto pekee"</string>
@@ -380,7 +368,7 @@
<string name="debug_input_category" msgid="7349460906970849771">"Ingizo"</string>
<string name="debug_drawing_category" msgid="5066171112313666619">"Uchoraji"</string>
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Utekelezaji wa maunzi ulioharakishwa"</string>
- <string name="media_category" msgid="8122076702526144053">"Vyombo vya Habari"</string>
+ <string name="media_category" msgid="8122076702526144053">"Maudhui"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Ufuatiliaji"</string>
<string name="strict_mode" msgid="889864762140862437">"Hali makinifu imewashwa"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Fanya skrini imemeteke programu zinapoendeleza shughuli ndefu kwenye skrini kuu"</string>
@@ -733,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Isiyobainika"</string>
<string name="feminine" msgid="1529155595310784757">"Jinsia ya kike"</string>
<string name="masculine" msgid="4653978041013996303">"Jinsia ya kiume"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Masasisho ya Mfumo"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index 8097be0..7c87eb7 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"இணைக்கப்பட்டது (மொபைல் இல்லை), பேட்டரி <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"இணைக்கப்பட்டது (மீடியா இல்லை), பேட்டரி <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"இணைக்கப்பட்டது (மொபைல் அல்லது மீடியா இல்லை), பேட்டரி <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"செயலிலுள்ளது. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> பேட்டரி."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"செயலிலுள்ளது. இடது பேட்டரி: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, வலது பேட்டரி: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"செயலில் உள்ளது. இடது: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> பேட்டரி."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"செயலில் உள்ளது. வலது: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> பேட்டரி."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> பேட்டரி"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"பேட்டரி <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"இடது பேட்டரி: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, வலது பேட்டரி: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"இடது: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> பேட்டரி"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"வலது: - <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> பேட்டரி"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"செயலில் உள்ளது"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"சேமிக்கப்பட்டது"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"செயலில் உள்ளது (இடதுபுறம் மட்டும்)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"செயலில் உள்ளது (வலதுபுறம் மட்டும்)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"செயலில் உள்ளது (இடது மற்றும் வலதுபுறம்)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"செயலிலுள்ளது (மீடியா மட்டும்). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> பேட்டரி."</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"செயலிலுள்ளது (மீடியா மட்டும்). இடது பேட்டரி: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, வலது பேட்டரி: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"இணைக்கப்பட்டுள்ளது (ஆடியோ பகிர்வை ஆதரிக்கிறது). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> பேட்டரி."</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"இணைக்கப்பட்டுள்ளது (ஆடியோ பகிர்வை ஆதரிக்கிறது). இடது பேட்டரி: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, வலது பேட்டரி: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"இணைக்கப்பட்டுள்ளது (ஆடியோ பகிர்வை ஆதரிக்கிறது). இடது: - <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> பேட்டரி."</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"இணைக்கப்பட்டுள்ளது (ஆடியோ பகிர்வை ஆதரிக்கிறது). வலது: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> பேட்டரி."</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"இணைக்கப்பட்டுள்ளது (ஆடியோ பகிர்வை ஆதரிக்கிறது)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"செயலிலுள்ளது (மீடியா மட்டும்)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"ஆடியோ பகிர்வை ஆதரிக்கிறது"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"செயலிலுள்ளது (மீடியா மட்டும்), இடதுபுறம் மட்டும்"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"அஃறிணை"</string>
<string name="feminine" msgid="1529155595310784757">"பெண்"</string>
<string name="masculine" msgid="4653978041013996303">"ஆண்"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"சிஸ்டம் புதுப்பிப்புகள்"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index fbedf33..689ea6f1 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -96,10 +96,8 @@
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"కనెక్ట్ చేయబడింది (ఫోన్ లేదా మీడియా కాదు), బ్యాటరీ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_active_battery_level" msgid="2685517576209066008">"యాక్టివ్గా ఉంది. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> బ్యాటరీ."</string>
<string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"యాక్టివ్గా ఉంది. ఎడమ వైపు: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, కుడివైపు: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> బ్యాటరీ."</string>
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"యాక్టివ్గా ఉంది. ఎడమ వైపు: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> బ్యాటరీ."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"యాక్టివ్గా ఉంది. కుడి వైపు: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> బ్యాటరీ."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> బ్యాటరీ"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"బ్యాటరీ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"ఎడమ వైపు: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, కుడివైపు: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> బ్యాటరీ."</string>
@@ -107,12 +105,9 @@
<string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"కుడి వైపు: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> బ్యాటరీ"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"యాక్టివ్గా ఉంది"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"సేవ్ చేయబడింది"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"యాక్టివ్గా ఉంది (ఎడమ వైపు మాత్రమే)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"యాక్టివ్గా ఉంది (కుడి వైపు మాత్రమే)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"యాక్టివ్గా ఉంది (ఎడమ వైపు, కుడి వైపు)"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"యాక్టివ్ (మీడియా మాత్రమే). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> బ్యాటరీ."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"యాక్టివ్ (మీడియా మాత్రమే). ఎడమ వైపు: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> బ్యాటరీ, కుడివైపు: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> బ్యాటరీ."</string>
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"కనెక్ట్ చేయబడింది (ఆడియో షేరింగ్కు సపోర్ట్ చేస్తుంది). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> బ్యాటరీ."</string>
@@ -164,7 +159,7 @@
<string name="bluetooth_pairing_decline" msgid="6483118841204885890">"రద్దు చేయండి"</string>
<string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"పెయిర్ చేయడం వలన కనెక్ట్ చేయబడినప్పుడు మీ కాంటాక్ట్లకు అలాగే కాల్ హిస్టరీకి యాక్సెస్ను మంజూరు చేస్తుంది."</string>
<string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>తో జత చేయడం సాధ్యపడలేదు."</string>
- <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"PIN లేదా పాస్కీ చెల్లని కారణంగా <xliff:g id="DEVICE_NAME">%1$s</xliff:g>తో పెయిర్ చేయడం సాధ్యపడలేదు."</string>
+ <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"PIN గానీ, పాస్కీ గానీ చెల్లని కారణంగా <xliff:g id="DEVICE_NAME">%1$s</xliff:g>తో పెయిర్ చేయడం సాధ్యపడలేదు."</string>
<string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>తో కమ్యూనికేట్ చేయడం సాధ్యపడదు."</string>
<string name="bluetooth_pairing_rejected_error_message" msgid="5943444352777314442">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> జత చేయడాన్ని తిరస్కరించింది."</string>
<string name="bluetooth_talkback_computer" msgid="3736623135703893773">"కంప్యూటర్"</string>
@@ -726,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"తటస్థం"</string>
<string name="feminine" msgid="1529155595310784757">"స్త్రీ"</string>
<string name="masculine" msgid="4653978041013996303">"పురుషుడు"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"సిస్టమ్ అప్డేట్లు"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 8f59f36..1899914 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"เชื่อมต่อแล้ว (ไม่รวมโทรศัพท์) แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"เชื่อมต่อแล้ว (ไม่รวมสื่อ) แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"เชื่อมต่อแล้ว (ไม่รวมโทรศัพท์หรือสื่อ) แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"ใช้งานอยู่ แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"ใช้งานอยู่ L: แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"ใช้งานอยู่ L: แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"ใช้งานอยู่ R: แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"L: แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"ซ้าย: แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"ขวา: แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"ใช้งานอยู่"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"บันทึกแล้ว"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"ใช้งานอยู่ (เฉพาะข้างซ้าย)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"ใช้งานอยู่ (เฉพาะข้างขวา)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"ใช้งานอยู่ (ข้างซ้ายและขวา)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"ใช้งานอยู่ (สื่อเท่านั้น) แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"ใช้งานอยู่ (สื่อเท่านั้น) L: แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"เชื่อมต่อแล้ว (รองรับการแชร์เสียง) แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"เชื่อมต่อแล้ว (รองรับการแชร์เสียง) L: แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"เชื่อมต่อแล้ว (รองรับการแชร์เสียง) ซ้าย: แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"เชื่อมต่อแล้ว (รองรับการแชร์เสียง) ขวา: แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"เชื่อมต่อแล้ว (รองรับการแชร์เสียง)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"ใช้งานอยู่ (สื่อเท่านั้น)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"รองรับการแชร์เสียง"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"ใช้งานอยู่ (สื่อเท่านั้น), ซ้ายเท่านั้น"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"ไม่มีเพศ"</string>
<string name="feminine" msgid="1529155595310784757">"เพศหญิง"</string>
<string name="masculine" msgid="4653978041013996303">"เพศชาย"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"การอัปเดตระบบ"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 58b6e84..64f5190 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Nakakonekta (walang telepono), baterya <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Nakakonekta (walang media), baterya <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Nakakonekta (walang telepono o media), baterya <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Aktibo. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterya."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Aktibo. L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> baterya."</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Aktibo. L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterya."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Aktibo. R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterya."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterya"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Baterya <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> baterya."</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"Kaliwa: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterya"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Kanan: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterya"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktibo"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Na-save"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Aktibo (kaliwa lang)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Aktibo (kanan lang)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Aktibo (kaliwa at kanan)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktibo (media lang). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterya."</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktibo (media lang). L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> baterya."</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Nakakonekta (sinusuportahan ang pag-share ng audio), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterya."</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Nakakonekta (sinusuportahan ang pag-share ng audio). L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> baterya."</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Nakakonekta (sinusuportahan ang pag-share ng audio). Kaliwa: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterya."</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Nakakonekta (sinusuportahan ang pag-share ng audio). Kanan: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterya."</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Nakakonekta (sinusuportahan ang pag-share ng audio)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktibo (media lang)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Sinusuportahan ang pag-share ng audio"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktibo (media lang), kaliwa lang"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Walang Kasarian"</string>
<string name="feminine" msgid="1529155595310784757">"Pambabae"</string>
<string name="masculine" msgid="4653978041013996303">"Panlalaki"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Mga Update sa System"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 0300ddc..144c20b 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> cihazına bağlandı (telefon yok), pil <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> cihazına bağlandı (medya yok), pil <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> cihazına bağlandı (telefon veya medya yok), pil seviyesi <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Etkin. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> pil seviyesi."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Etkin. Sol: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Sağ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> pil seviyesi."</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Etkin. Sol: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> pil seviyesi."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Etkin. Sağ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> pil seviyesi."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Pil düzeyi <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Pil <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"Sol: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Sağ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> pil seviyesi."</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"Sol: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> pil seviyesi"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Sağ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> pil seviyesi."</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Etkin"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Kaydedildi"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Etkin (yalnızca sol taraf)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Etkin (yalnızca sağ taraf)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Etkin (sol ve sağ taraf)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Etkin (yalnızca medya). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> pil seviyesi."</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Etkin (yalnızca medya), Sol: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Sağ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> pil seviyesi."</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Bağlı (ses paylaşımını destekler), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> pil seviyesi."</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Bağlı (ses paylaşımını destekler), Sol: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Sağ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> pil seviyesi."</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Bağlı (ses paylaşımını destekler). Sol: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> pil seviyesi."</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Bağlı (ses paylaşımını destekler). Sağ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> pil seviyesi."</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Bağlı (ses paylaşımını destekler)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Etkin (yalnızca medya)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Ses paylaşımını destekler"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Etkin (yalnızca medya), yalnızca sol"</string>
@@ -507,10 +490,10 @@
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - Tamamen şarj olmasına <xliff:g id="TIME">%2$s</xliff:g> kaldı"</string>
<string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Şarj işlemi optimize edildi"</string>
<string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> ‑ Şarj ediliyor"</string>
- <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Tamamen dolacağı zaman: <xliff:g id="TIME">%3$s</xliff:g>"</string>
- <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Tamamen şarj olacağı zaman: <xliff:g id="TIME">%2$s</xliff:g>"</string>
- <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Tamamen şarj olacağı zaman: <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Tamamen dolacağı zaman: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g> içinde tamamen dolacak"</string>
+ <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> içinde tamamen şarj olacak"</string>
+ <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"<xliff:g id="TIME">%1$s</xliff:g> içinde tamamen şarj olacak"</string>
+ <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"<xliff:g id="TIME">%1$s</xliff:g> içinde tamamen dolacak"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Bilinmiyor"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Şarj oluyor"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Hızlı şarj oluyor"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Cinsiyetsiz"</string>
<string name="feminine" msgid="1529155595310784757">"Kadın"</string>
<string name="masculine" msgid="4653978041013996303">"Erkek"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Sistem Güncellemeleri"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index 807bc51..ecfa2c9 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> під’єднано (без телефона), заряд акумулятора – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> під’єднано (без медіа), заряд акумулятора – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> під’єднано (без телефона й медіа), заряд акумулятора – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Активне з’єднання. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> заряду акумулятора."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Активне з’єднання. Лівий: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, правий: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> заряду акумулятора."</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Активовано. Лівий: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> заряду акумулятора."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Активовано. Правий: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> заряду акумулятора."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> заряду акумулятора"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Заряд акумулятора: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"Лівий: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, правий: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> заряду акумулятора."</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"Лівий: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> заряду акумулятора"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Правий: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> заряду акумулятора"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Активовано"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Збережено"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Активовано (лише лівий)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Активовано (лише правий)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Активовано (лівий і правий)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Активне з’єднання (лише для мультимедіа). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> заряду акумулятора."</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Активне з’єднання (лише для мультимедіа). Лівий: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, правий: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> заряду акумулятора"</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Підключено (підтримує надсилання аудіо). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> заряду акумулятора."</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Підключено (підтримує надсилання аудіо). Лівий: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, правий: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> заряду акумулятора."</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Підключено (підтримує надсилання аудіо). Лівий: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> заряду акумулятора."</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Підключено (підтримує надсилання аудіо). Правий: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> заряду акумулятора."</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Підключено (підтримує надсилання аудіо)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Активно (лише для мультимедіа)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Підтримує надсилання аудіо"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Активно (лише для мультимедіа); лише лівий"</string>
@@ -252,7 +235,7 @@
<string name="choose_profile" msgid="343803890897657450">"Вибрати профіль"</string>
<string name="category_personal" msgid="6236798763159385225">"Особисті"</string>
<string name="category_work" msgid="4014193632325996115">"Робочі"</string>
- <string name="category_private" msgid="4244892185452788977">"Приватні"</string>
+ <string name="category_private" msgid="4244892185452788977">"Приватний простір"</string>
<string name="category_clone" msgid="1554511758987195974">"Копія профілю"</string>
<string name="development_settings_title" msgid="140296922921597393">"Параметри розробника"</string>
<string name="development_settings_enable" msgid="4285094651288242183">"Увімкнути параметри розробника"</string>
@@ -613,7 +596,7 @@
<string name="help_label" msgid="3528360748637781274">"Довідка й відгуки"</string>
<string name="storage_category" msgid="2287342585424631813">"Пам\'ять"</string>
<string name="shared_data_title" msgid="1017034836800864953">"Спільні дані"</string>
- <string name="shared_data_summary" msgid="5516326713822885652">"Переглянути та змінити спільні дані"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Переглянути й змінити спільні дані"</string>
<string name="shared_data_no_blobs_text" msgid="3108114670341737434">"Немає спільних даних для цього користувача."</string>
<string name="shared_data_query_failure_text" msgid="3489828881998773687">"Не вдалось отримати спільні дані. Повторіть спробу."</string>
<string name="blob_id_text" msgid="8680078988996308061">"Ідентифікатор спільних даних: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Середній рід"</string>
<string name="feminine" msgid="1529155595310784757">"Жіночий рід"</string>
<string name="masculine" msgid="4653978041013996303">"Чоловічий рід"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Оновлення системи"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index 8084162..4286c81 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -96,10 +96,8 @@
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"منسلک ہے (فون یا میڈیا کے علاوہ)، بیٹری <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_active_battery_level" msgid="2685517576209066008">"فعال۔ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> بیٹری۔"</string>
<string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"فعال۔ L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>، R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> بیٹری۔"</string>
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"فعال ہے۔ بایاں: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> بیٹری۔"</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"فعال ہے۔ دایاں: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> بیٹری۔"</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> بیٹری"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"بیٹری <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>، R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> بیٹری۔"</string>
@@ -107,12 +105,9 @@
<string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"دائيں: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> بیٹری"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"فعال"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"محفوظ ہے"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"فعال ہے (صرف بایاں)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"فعال ہے (صرف دایاں)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"فعال ہے (بایاں اور دایاں)"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"فعال (صرف میڈیا)۔ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> بیٹری۔"</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"فعال (صرف میڈیا)۔ L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>، R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> بیٹری۔"</string>
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"منسلک ہے (آڈیو کے اشتراک کو سپورٹ کرتا ہے)۔ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> بیٹری۔"</string>
@@ -726,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"غیر واضح"</string>
<string name="feminine" msgid="1529155595310784757">"مؤنث"</string>
<string name="masculine" msgid="4653978041013996303">"مذکر"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"سسٹم اپ ڈیٹس"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index 4415667..104f27b 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> ulandi (telefondan tashqari), batareya quvvati: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> ulandi (mediadan tashqari), batareya quvvati: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> ulandi (telefon yoki mediadan tashqari), batareya quvvati: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Faol. Quvvat: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Faol. Quvvat: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> (L), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> (R)."</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Faol. L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> quvvat"</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Faol. R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> quvvat"</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Batareya quvvati: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Batareya: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"Quvvat: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> (L), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> (R)."</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"Quvvat: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> (chap)"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Quvvat: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> (oʻng)."</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Faol"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Saqlangan"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Faol (faqat chap)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Faol (faqat oʻng)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Faol (chap va oʻng)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Faol (faqat media uchun) Quvvat: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Faol (faqat media uchun), quvvat: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> (L), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> (R)"</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Ulangan (audio yuborish mumkin), quvvat: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Ulangan (audio yuborish mumkin), quvvat: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> (L), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> (R)"</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Ulangan (audio yuborish mumkin). Quvvat: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> (chap)."</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Ulangan (audio yuborish mumkin). Quvvat: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> (oʻng)."</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Ulangan (audio yuborish mumkin)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Faol (faqat media uchun)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Audio yuborishi mumkin"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Faol (faqat media uchun), faqat chap"</string>
@@ -252,7 +235,7 @@
<string name="choose_profile" msgid="343803890897657450">"Profilni tanlang"</string>
<string name="category_personal" msgid="6236798763159385225">"Shaxsiy"</string>
<string name="category_work" msgid="4014193632325996115">"Ish"</string>
- <string name="category_private" msgid="4244892185452788977">"Yopiq"</string>
+ <string name="category_private" msgid="4244892185452788977">"Maxfiy"</string>
<string name="category_clone" msgid="1554511758987195974">"Nusxalash"</string>
<string name="development_settings_title" msgid="140296922921597393">"Dasturchi sozlamalari"</string>
<string name="development_settings_enable" msgid="4285094651288242183">"Dasturchi sozlamalarini yoqish"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Oʻrta"</string>
<string name="feminine" msgid="1529155595310784757">"Ayollar uchun"</string>
<string name="masculine" msgid="4653978041013996303">"Erkaklar uchun"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Tizim yangilanishi"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index f33d909..2ed847c 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Đã kết nối (không có điện thoại), mức pin <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Đã kết nối (không có phương tiện), mức pin <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Đã kết nối (không có điện thoại hoặc phương tiện), mức pin <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Đang hoạt động. Còn <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> pin."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Đang hoạt động. Bên trái: Còn <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> pin. Bên phải: Còn <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> pin."</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Đang hoạt động. Tai trái: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> pin."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Đang hoạt động. Tai phải: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> pin."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Mức pin <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Pin <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"Bên trái: Còn <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> pin. Bên phải: Còn <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> pin."</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"Bên trái: Còn <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> pin"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Bên phải: Còn <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> pin"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Đang hoạt động"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Đã lưu"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Đang hoạt động (chỉ tai trái)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Đang hoạt động (chỉ tai phải)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Đang hoạt động (cả tai phải và tai trái)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Đang hoạt động (chỉ phát nội dung đa phương tiện). Còn <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> pin."</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Đang hoạt động (chỉ phát nội dung đa phương tiện). Bên trái: Còn <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> pin. Bên phải: Còn <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> pin."</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Đã kết nối (có hỗ trợ tính năng chia sẻ âm thanh). Còn <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> pin."</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Đã kết nối (có hỗ trợ tính năng chia sẻ âm thanh). Bên trái: Còn <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> pin. Bên phải: Còn <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> pin."</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Đã kết nối (có hỗ trợ tính năng chia sẻ âm thanh). Bên trái: Còn <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> pin."</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Đã kết nối (có hỗ trợ tính năng chia sẻ âm thanh). Bên phải: Còn <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> pin."</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Đã kết nối (có hỗ trợ tính năng chia sẻ âm thanh)."</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Đang hoạt động (chỉ phát nội dung đa phương tiện)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Hỗ trợ tính năng chia sẻ âm thanh"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Đang hoạt động (chỉ phát nội dung đa phương tiện), chỉ dùng tai nghe bên trái"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Vô tính"</string>
<string name="feminine" msgid="1529155595310784757">"Giống cái"</string>
<string name="masculine" msgid="4653978041013996303">"Giống đực"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Cập nhật hệ thống"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rCN/arrays.xml b/packages/SettingsLib/res/values-zh-rCN/arrays.xml
index 432dd5f..939b4ec 100644
--- a/packages/SettingsLib/res/values-zh-rCN/arrays.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/arrays.xml
@@ -257,7 +257,7 @@
<item msgid="1212561935004167943">"以绿色突出显示测试绘制命令"</item>
</string-array>
<string-array name="track_frame_time_entries">
- <item msgid="634406443901014984">"关闭"</item>
+ <item msgid="634406443901014984">"已关闭"</item>
<item msgid="1288760936356000927">"在屏幕上显示为条形图"</item>
<item msgid="5023908510820531131">"在 <xliff:g id="AS_TYPED_COMMAND">adb shell dumpsys gfxinfo</xliff:g> 中"</item>
</string-array>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 816ba8d..56282ec 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"已连接(无手机信号),电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"已连接(无媒体信号),电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"已连接(无手机或媒体信号),电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"使用中。电池电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>。"</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"使用中。左侧电池电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>,右侧电池电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>。"</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"使用中。左侧剩余电量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>。"</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"使用中。右侧剩余电量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>。"</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> 的电量"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"电池电量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"左侧电池电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>,右侧电池电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>。"</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"左侧电池电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"右侧电池电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"使用中"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"已保存的设备"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"使用中(仅左耳助听器)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"使用中(仅右耳助听器)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"使用中(左右耳助听器)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"使用中(仅限媒体)。电池电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>。"</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"使用中(仅限媒体)。左侧电池电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>,右侧电池电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>。"</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"已连接(支持音频分享)。电池电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>。"</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"已连接(支持音频分享)。左侧电池电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>,右侧电池电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>。"</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"已连接(支持音频分享)。左侧电池电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>。"</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"已连接(支持音频分享)。右侧电池电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>。"</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"已连接(支持音频分享)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"使用中(仅限媒体)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"支持音频分享"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"使用中(仅限媒体),仅左侧"</string>
@@ -252,7 +235,7 @@
<string name="choose_profile" msgid="343803890897657450">"选择个人资料"</string>
<string name="category_personal" msgid="6236798763159385225">"个人"</string>
<string name="category_work" msgid="4014193632325996115">"工作"</string>
- <string name="category_private" msgid="4244892185452788977">"私享"</string>
+ <string name="category_private" msgid="4244892185452788977">"私密"</string>
<string name="category_clone" msgid="1554511758987195974">"克隆"</string>
<string name="development_settings_title" msgid="140296922921597393">"开发者选项"</string>
<string name="development_settings_enable" msgid="4285094651288242183">"启用开发者选项"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"中性"</string>
<string name="feminine" msgid="1529155595310784757">"阴性"</string>
<string name="masculine" msgid="4653978041013996303">"阳性"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"系统更新"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index b26efb2..60c71e0 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"已連接 (無手機音訊),電量為 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"已連接 (無媒體音訊),電量為 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"已連接 (無手機或媒體音訊),電量為 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"啟用。<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> 電量。"</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"啟用。左側:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>,右側:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> 電量。"</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"使用中。左側:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> 電量。"</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"使用中。右側:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> 電量。"</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"左側:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>,右側:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> 電量。"</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"左側:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> 電量"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"右側:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> 電量。"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"使用中"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"已儲存"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"使用中 (僅左側)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"使用中 (僅右側)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"使用中 (左右兩側)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"啟用 (只限媒體)。<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> 電量。"</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"啟用 (只限媒體),左側:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> 電量,右側:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> 電量。"</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"已連線 (支援音訊分享功能),<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> 電量。"</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"已連線 (支援音訊分享功能),左側:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> 電量,右側:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> 電量。"</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"已連線 (支援音訊分享功能)。左側:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> 電量。"</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"已連線 (支援音訊分享功能)。右側:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> 電量。"</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"已連線 (支援音訊分享功能)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"啟用 (只限媒體)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"支援音訊分享功能"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"左側啟用 (只限媒體)"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"中性"</string>
<string name="feminine" msgid="1529155595310784757">"女性"</string>
<string name="masculine" msgid="4653978041013996303">"男性"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"系統更新"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 149022c..6159736 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -94,44 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"已連線 (無手機音訊),電量為 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"已連線 (無媒體音訊),電量為 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"已連線 (無手機或媒體音訊),電量為 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"已啟用。電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>。"</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"已啟用。左側電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>,右側電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>。"</string>
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"使用中。左:電量為 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>。"</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"使用中。右:電量為 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>。"</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"左側電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>,右側電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>。"</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"左側電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"右側電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"使用中"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"已儲存"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"使用中 (僅左側)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"使用中 (僅右側)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"使用中 (左右兩側)"</string>
+ <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"已啟用 (僅限媒體)。電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>。"</string>
+ <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"已啟用 (僅限媒體)。左側電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>,右側電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>。"</string>
+ <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"已連線 (支援音訊分享)。電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>。"</string>
+ <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"已連線 (支援音訊分享)。左側電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>,右側電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>。"</string>
+ <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"已連線 (支援音訊分享)。左側電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>。"</string>
+ <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"已連線 (支援音訊分享)。右側電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>。"</string>
+ <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"已連線 (支援音訊分享)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"啟用 (僅限媒體)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"支援音訊分享"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"左側啟用 (僅限媒體)"</string>
@@ -738,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"中性"</string>
<string name="feminine" msgid="1529155595310784757">"陰性"</string>
<string name="masculine" msgid="4653978041013996303">"陽性"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"系統更新"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 8448814..0200c01 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -96,10 +96,8 @@
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Ixhunyiwe (ayikho ifoni noma imidiya), ibhethri ngu-<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Iyasebenza. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ibhethri."</string>
<string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Iyasebenza. L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ibhethri."</string>
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
- <skip />
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Iyasebenza. L: U-<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> webhethri"</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Iyasebenza. R: U-<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> webhethri"</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ibhethri"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Ibhethri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ibhethri."</string>
@@ -107,12 +105,9 @@
<string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Kwesokudla: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ibhethri"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Iyasebenza"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Ilondoloziwe"</string>
- <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
- <skip />
- <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Iyasebenza (ngakwesokunxele kuphela)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Iyasebenza (ngakwesokudla kuphela)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Iyasebenza (ngakwesokunxele nakwesokudla)"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Iyasebenza (imidiya kuphela). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ibhethri."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Iyasebenza (imidiya kuphela). L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ibhethri."</string>
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Ixhunyiwe (isekela ukwabelana ngokuqoshiwe). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ibhethri."</string>
@@ -726,4 +721,5 @@
<string name="neuter" msgid="2075249330106127310">"Okungenabulili"</string>
<string name="feminine" msgid="1529155595310784757">"Okwabesifazane"</string>
<string name="masculine" msgid="4653978041013996303">"Okwabesilisa"</string>
+ <string name="system_update_settings_list_item_title" msgid="6618098383615432484">"Izibuyekezo Zesistimu"</string>
</resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/RecentAppOpsAccess.java b/packages/SettingsLib/src/com/android/settingslib/applications/RecentAppOpsAccess.java
index 169c330..57bde56 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/RecentAppOpsAccess.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/RecentAppOpsAccess.java
@@ -29,6 +29,7 @@
import android.os.UserManager;
import android.permission.PermissionManager;
import android.text.format.DateUtils;
+import android.util.ArrayMap;
import android.util.IconDrawableFactory;
import android.util.Log;
@@ -127,6 +128,7 @@
final long now = mClock.millis();
final UserManager um = mContext.getSystemService(UserManager.class);
final List<UserHandle> profiles = um.getUserProfiles();
+ ArrayMap<UserHandle, Boolean> shouldIncludeAppsByUsers = new ArrayMap<>();
for (int i = 0; i < appOpsCount; ++i) {
AppOpsManager.PackageOps ops = appOps.get(i);
@@ -134,9 +136,13 @@
int uid = ops.getUid();
UserHandle user = UserHandle.getUserHandleForUid(uid);
+ if (!shouldIncludeAppsByUsers.containsKey(user)) {
+ shouldIncludeAppsByUsers.put(user, shouldHideUser(um, user));
+ }
+
// Don't show apps belonging to background users except for profiles that shouldn't
// be shown in quiet mode.
- if (!profiles.contains(user) || isHideInQuietEnabledForProfile(um, user)) {
+ if (!profiles.contains(user) || !shouldIncludeAppsByUsers.get(user)) {
continue;
}
@@ -200,7 +206,7 @@
return accesses;
}
- private boolean isHideInQuietEnabledForProfile(UserManager userManager, UserHandle userHandle) {
+ private boolean shouldHideUser(UserManager userManager, UserHandle userHandle) {
if (android.multiuser.Flags.enablePrivateSpaceFeatures()
&& android.multiuser.Flags.handleInterleavedSettingsForPrivateSpace()) {
return userManager.isQuietModeEnabled(userHandle)
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index a7b7da5..30bec77 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -649,6 +649,9 @@
for (CachedBluetoothDevice cbd : mMemberDevices) {
cbd.setName(name);
}
+ if (mSubDevice != null) {
+ mSubDevice.setName(name);
+ }
}
/**
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
index 4e52c77..cb6a930 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
@@ -176,6 +176,22 @@
}
/**
+ * Sync device status of the pair of the hearing aid if needed.
+ *
+ * @param device the remote device
+ */
+ public synchronized void syncDeviceWithinHearingAidSetIfNeeded(CachedBluetoothDevice device,
+ int state, int profileId) {
+ if (profileId == BluetoothProfile.HAP_CLIENT
+ || profileId == BluetoothProfile.HEARING_AID
+ || profileId == BluetoothProfile.CSIP_SET_COORDINATOR) {
+ if (state == BluetoothProfile.STATE_CONNECTED) {
+ mHearingAidDeviceManager.syncDeviceIfNeeded(device);
+ }
+ }
+ }
+
+ /**
* Search for existing sub device {@link CachedBluetoothDevice}.
*
* @param device the address of the Bluetooth device
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidDeviceManager.java
index 1069b71..ed964a9 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidDeviceManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidDeviceManager.java
@@ -15,6 +15,8 @@
*/
package com.android.settingslib.bluetooth;
+import android.bluetooth.BluetoothCsipSetCoordinator;
+import android.bluetooth.BluetoothHapClient;
import android.bluetooth.BluetoothHearingAid;
import android.bluetooth.BluetoothLeAudio;
import android.bluetooth.BluetoothProfile;
@@ -98,6 +100,7 @@
// device.
if (hearingAidDevice != null) {
hearingAidDevice.setSubDevice(newDevice);
+ newDevice.setName(hearingAidDevice.getName());
return true;
}
}
@@ -108,6 +111,10 @@
return hiSyncId != BluetoothHearingAid.HI_SYNC_ID_INVALID;
}
+ private boolean isValidGroupId(int groupId) {
+ return groupId != BluetoothCsipSetCoordinator.GROUP_ID_INVALID;
+ }
+
private CachedBluetoothDevice getCachedDevice(long hiSyncId) {
for (int i = mCachedDevices.size() - 1; i >= 0; i--) {
CachedBluetoothDevice cachedDevice = mCachedDevices.get(i);
@@ -258,6 +265,27 @@
}
}
+ void syncDeviceIfNeeded(CachedBluetoothDevice device) {
+ final LocalBluetoothProfileManager profileManager = mBtManager.getProfileManager();
+ final HapClientProfile hap = profileManager.getHapClientProfile();
+ // Sync preset if device doesn't support synchronization on the remote side
+ if (hap != null && !hap.supportsSynchronizedPresets(device.getDevice())) {
+ final CachedBluetoothDevice mainDevice = findMainDevice(device);
+ if (mainDevice != null) {
+ int mainPresetIndex = hap.getActivePresetIndex(mainDevice.getDevice());
+ int presetIndex = hap.getActivePresetIndex(device.getDevice());
+ if (mainPresetIndex != BluetoothHapClient.PRESET_INDEX_UNAVAILABLE
+ && mainPresetIndex != presetIndex) {
+ if (DEBUG) {
+ Log.d(TAG, "syncing preset from " + presetIndex + "->"
+ + mainPresetIndex + ", device=" + device);
+ }
+ hap.selectPreset(device.getDevice(), mainPresetIndex);
+ }
+ }
+ }
+ }
+
private void setAudioRoutingConfig(CachedBluetoothDevice device) {
AudioDeviceAttributes hearingDeviceAttributes =
mRoutingHelper.getMatchedHearingDeviceAttributes(device);
@@ -326,7 +354,19 @@
}
CachedBluetoothDevice findMainDevice(CachedBluetoothDevice device) {
+ if (device == null || mCachedDevices == null) {
+ return null;
+ }
+
for (CachedBluetoothDevice cachedDevice : mCachedDevices) {
+ if (isValidGroupId(cachedDevice.getGroupId())) {
+ Set<CachedBluetoothDevice> memberSet = cachedDevice.getMemberDevice();
+ for (CachedBluetoothDevice memberDevice : memberSet) {
+ if (memberDevice != null && memberDevice.equals(device)) {
+ return cachedDevice;
+ }
+ }
+ }
if (isValidHiSyncId(cachedDevice.getHiSyncId())) {
CachedBluetoothDevice subDevice = cachedDevice.getSubDevice();
if (subDevice != null && subDevice.equals(device)) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidStatsLogUtils.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidStatsLogUtils.java
index 8e3df8b..2de2174 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidStatsLogUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidStatsLogUtils.java
@@ -48,17 +48,15 @@
private static final String BT_HEARING_AIDS_PAIRED_HISTORY = "bt_hearing_aids_paired_history";
private static final String BT_HEARING_AIDS_CONNECTED_HISTORY =
"bt_hearing_aids_connected_history";
- private static final String BT_HEARING_DEVICES_PAIRED_HISTORY =
+ private static final String BT_HEARABLE_DEVICES_PAIRED_HISTORY =
"bt_hearing_devices_paired_history";
- private static final String BT_HEARING_DEVICES_CONNECTED_HISTORY =
+ private static final String BT_HEARABLE_DEVICES_CONNECTED_HISTORY =
"bt_hearing_devices_connected_history";
- private static final String BT_HEARING_USER_CATEGORY = "bt_hearing_user_category";
-
private static final String HISTORY_RECORD_DELIMITER = ",";
static final String CATEGORY_HEARING_AIDS = "A11yHearingAidsUser";
static final String CATEGORY_NEW_HEARING_AIDS = "A11yNewHearingAidsUser";
- static final String CATEGORY_HEARING_DEVICES = "A11yHearingDevicesUser";
- static final String CATEGORY_NEW_HEARING_DEVICES = "A11yNewHearingDevicesUser";
+ static final String CATEGORY_HEARABLE_DEVICES = "A11yHearingDevicesUser";
+ static final String CATEGORY_NEW_HEARABLE_DEVICES = "A11yNewHearingDevicesUser";
static final int PAIRED_HISTORY_EXPIRED_DAY = 30;
static final int CONNECTED_HISTORY_EXPIRED_DAY = 7;
@@ -73,14 +71,14 @@
HistoryType.TYPE_UNKNOWN,
HistoryType.TYPE_HEARING_AIDS_PAIRED,
HistoryType.TYPE_HEARING_AIDS_CONNECTED,
- HistoryType.TYPE_HEARING_DEVICES_PAIRED,
- HistoryType.TYPE_HEARING_DEVICES_CONNECTED})
+ HistoryType.TYPE_HEARABLE_DEVICES_PAIRED,
+ HistoryType.TYPE_HEARABLE_DEVICES_CONNECTED})
public @interface HistoryType {
int TYPE_UNKNOWN = -1;
int TYPE_HEARING_AIDS_PAIRED = 0;
int TYPE_HEARING_AIDS_CONNECTED = 1;
- int TYPE_HEARING_DEVICES_PAIRED = 2;
- int TYPE_HEARING_DEVICES_CONNECTED = 3;
+ int TYPE_HEARABLE_DEVICES_PAIRED = 2;
+ int TYPE_HEARABLE_DEVICES_CONNECTED = 3;
}
private static final HashMap<String, Integer> sDeviceAddressToBondEntryMap = new HashMap<>();
@@ -127,8 +125,8 @@
}
/**
- * Updates corresponding history if we found the device is a hearing device after profile state
- * changed.
+ * Updates corresponding history if we found the device is a hearing related device after
+ * profile state changed.
*
* @param context the request context
* @param cachedDevice the remote device
@@ -148,7 +146,7 @@
} else if (cachedDevice.getProfiles().stream().anyMatch(
p -> (p instanceof A2dpSinkProfile || p instanceof HeadsetProfile))) {
HearingAidStatsLogUtils.addCurrentTimeToHistory(context,
- HearingAidStatsLogUtils.HistoryType.TYPE_HEARING_DEVICES_PAIRED);
+ HearingAidStatsLogUtils.HistoryType.TYPE_HEARABLE_DEVICES_PAIRED);
}
removeFromJustBonded(cachedDevice.getAddress());
}
@@ -161,7 +159,7 @@
HearingAidStatsLogUtils.HistoryType.TYPE_HEARING_AIDS_CONNECTED);
} else if (profile instanceof A2dpSinkProfile || profile instanceof HeadsetProfile) {
HearingAidStatsLogUtils.addCurrentTimeToHistory(context,
- HearingAidStatsLogUtils.HistoryType.TYPE_HEARING_DEVICES_CONNECTED);
+ HearingAidStatsLogUtils.HistoryType.TYPE_HEARABLE_DEVICES_CONNECTED);
}
}
}
@@ -169,18 +167,13 @@
/**
* Returns the user category if the user is already categorized. Otherwise, checks the
* history and sees if the user is categorized as one of {@link #CATEGORY_HEARING_AIDS},
- * {@link #CATEGORY_NEW_HEARING_AIDS}, {@link #CATEGORY_HEARING_DEVICES}, and
- * {@link #CATEGORY_NEW_HEARING_DEVICES}.
+ * {@link #CATEGORY_NEW_HEARING_AIDS}, {@link #CATEGORY_HEARABLE_DEVICES}, and
+ * {@link #CATEGORY_NEW_HEARABLE_DEVICES}.
*
* @param context the request context
* @return the category which user belongs to
*/
public static synchronized String getUserCategory(Context context) {
- String userCategory = getSharedPreferences(context).getString(BT_HEARING_USER_CATEGORY, "");
- if (!userCategory.isEmpty()) {
- return userCategory;
- }
-
LinkedList<Long> hearingAidsConnectedHistory = getHistory(context,
HistoryType.TYPE_HEARING_AIDS_CONNECTED);
if (hearingAidsConnectedHistory != null
@@ -192,29 +185,29 @@
// will be categorized as CATEGORY_HEARING_AIDS.
if (hearingAidsPairedHistory != null
&& hearingAidsPairedHistory.size() >= VALID_PAIRED_EVENT_COUNT) {
- userCategory = CATEGORY_NEW_HEARING_AIDS;
+ return CATEGORY_NEW_HEARING_AIDS;
} else {
- userCategory = CATEGORY_HEARING_AIDS;
+ return CATEGORY_HEARING_AIDS;
}
}
- LinkedList<Long> hearingDevicesConnectedHistory = getHistory(context,
- HistoryType.TYPE_HEARING_DEVICES_CONNECTED);
- if (hearingDevicesConnectedHistory != null
- && hearingDevicesConnectedHistory.size() >= VALID_CONNECTED_EVENT_COUNT) {
- LinkedList<Long> hearingDevicesPairedHistory = getHistory(context,
- HistoryType.TYPE_HEARING_DEVICES_PAIRED);
+ LinkedList<Long> hearableDevicesConnectedHistory = getHistory(context,
+ HistoryType.TYPE_HEARABLE_DEVICES_CONNECTED);
+ if (hearableDevicesConnectedHistory != null
+ && hearableDevicesConnectedHistory.size() >= VALID_CONNECTED_EVENT_COUNT) {
+ LinkedList<Long> hearableDevicesPairedHistory = getHistory(context,
+ HistoryType.TYPE_HEARABLE_DEVICES_PAIRED);
// Since paired history will be cleared after 30 days. If there's any record within 30
- // days, the user will be categorized as CATEGORY_NEW_HEARING_DEVICES. Otherwise, the
- // user will be categorized as CATEGORY_HEARING_DEVICES.
- if (hearingDevicesPairedHistory != null
- && hearingDevicesPairedHistory.size() >= VALID_PAIRED_EVENT_COUNT) {
- userCategory = CATEGORY_NEW_HEARING_DEVICES;
+ // days, the user will be categorized as CATEGORY_NEW_HEARABLE_DEVICES. Otherwise, the
+ // user will be categorized as CATEGORY_HEARABLE_DEVICES.
+ if (hearableDevicesPairedHistory != null
+ && hearableDevicesPairedHistory.size() >= VALID_PAIRED_EVENT_COUNT) {
+ return CATEGORY_NEW_HEARABLE_DEVICES;
} else {
- userCategory = CATEGORY_HEARING_DEVICES;
+ return CATEGORY_HEARABLE_DEVICES;
}
}
- return userCategory;
+ return "";
}
/**
@@ -245,7 +238,7 @@
}
/**
- * Adds current timestamp into BT hearing devices related history.
+ * Adds current timestamp into BT hearing related devices history.
* @param context the request context
* @param type the type of history to store the data. See {@link HistoryType}.
*/
@@ -279,13 +272,13 @@
static synchronized LinkedList<Long> getHistory(Context context, @HistoryType int type) {
String spName = HISTORY_TYPE_TO_SP_NAME_MAPPING.get(type);
if (BT_HEARING_AIDS_PAIRED_HISTORY.equals(spName)
- || BT_HEARING_DEVICES_PAIRED_HISTORY.equals(spName)) {
+ || BT_HEARABLE_DEVICES_PAIRED_HISTORY.equals(spName)) {
LinkedList<Long> history = convertToHistoryList(
getSharedPreferences(context).getString(spName, ""));
removeRecordsBeforeDay(history, PAIRED_HISTORY_EXPIRED_DAY);
return history;
} else if (BT_HEARING_AIDS_CONNECTED_HISTORY.equals(spName)
- || BT_HEARING_DEVICES_CONNECTED_HISTORY.equals(spName)) {
+ || BT_HEARABLE_DEVICES_CONNECTED_HISTORY.equals(spName)) {
LinkedList<Long> history = convertToHistoryList(
getSharedPreferences(context).getString(spName, ""));
removeRecordsBeforeDay(history, CONNECTED_HISTORY_EXPIRED_DAY);
@@ -352,9 +345,9 @@
HISTORY_TYPE_TO_SP_NAME_MAPPING.put(
HistoryType.TYPE_HEARING_AIDS_CONNECTED, BT_HEARING_AIDS_CONNECTED_HISTORY);
HISTORY_TYPE_TO_SP_NAME_MAPPING.put(
- HistoryType.TYPE_HEARING_DEVICES_PAIRED, BT_HEARING_DEVICES_PAIRED_HISTORY);
+ HistoryType.TYPE_HEARABLE_DEVICES_PAIRED, BT_HEARABLE_DEVICES_PAIRED_HISTORY);
HISTORY_TYPE_TO_SP_NAME_MAPPING.put(
- HistoryType.TYPE_HEARING_DEVICES_CONNECTED, BT_HEARING_DEVICES_CONNECTED_HISTORY);
+ HistoryType.TYPE_HEARABLE_DEVICES_CONNECTED, BT_HEARABLE_DEVICES_CONNECTED_HISTORY);
}
private HearingAidStatsLogUtils() {}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
index 4055986..8dfeb55 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
@@ -408,6 +408,8 @@
boolean needDispatchProfileConnectionState = true;
if (cachedDevice.getHiSyncId() != BluetoothHearingAid.HI_SYNC_ID_INVALID
|| cachedDevice.getGroupId() != BluetoothCsipSetCoordinator.GROUP_ID_INVALID) {
+ mDeviceManager.syncDeviceWithinHearingAidSetIfNeeded(cachedDevice, newState,
+ mProfile.getProfileId());
needDispatchProfileConnectionState = !mDeviceManager
.onProfileConnectionStateChangedIfProcessed(cachedDevice, newState,
mProfile.getProfileId());
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/session/MediaSessionManagerExt.kt b/packages/SettingsLib/src/com/android/settingslib/media/session/MediaSessionManagerExt.kt
index 68f471d..d198136 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/session/MediaSessionManagerExt.kt
+++ b/packages/SettingsLib/src/com/android/settingslib/media/session/MediaSessionManagerExt.kt
@@ -45,14 +45,13 @@
.buffer(capacity = Channel.CONFLATED)
/** [Flow] for [MediaSessionManager.RemoteSessionCallback]. */
-val MediaSessionManager.remoteSessionChanges: Flow<MediaSession.Token?>
+val MediaSessionManager.defaultRemoteSessionChanged: Flow<MediaSession.Token?>
get() =
callbackFlow {
val callback =
object : MediaSessionManager.RemoteSessionCallback {
- override fun onVolumeChanged(sessionToken: MediaSession.Token, flags: Int) {
- launch { send(sessionToken) }
- }
+ override fun onVolumeChanged(sessionToken: MediaSession.Token, flags: Int) =
+ Unit
override fun onDefaultRemoteSessionChanged(
sessionToken: MediaSession.Token?
diff --git a/packages/SettingsLib/src/com/android/settingslib/volume/data/repository/MediaControllerRepository.kt b/packages/SettingsLib/src/com/android/settingslib/volume/data/repository/MediaControllerRepository.kt
index e4ac9fe..195ccfc 100644
--- a/packages/SettingsLib/src/com/android/settingslib/volume/data/repository/MediaControllerRepository.kt
+++ b/packages/SettingsLib/src/com/android/settingslib/volume/data/repository/MediaControllerRepository.kt
@@ -21,6 +21,7 @@
import com.android.settingslib.bluetooth.LocalBluetoothManager
import com.android.settingslib.bluetooth.headsetAudioModeChanges
import com.android.settingslib.media.session.activeMediaChanges
+import com.android.settingslib.media.session.defaultRemoteSessionChanged
import com.android.settingslib.volume.shared.AudioManagerEventsReceiver
import com.android.settingslib.volume.shared.model.AudioManagerEvent
import kotlin.coroutines.CoroutineContext
@@ -59,6 +60,9 @@
override val activeSessions: StateFlow<List<MediaController>> =
merge(
+ mediaSessionManager.defaultRemoteSessionChanged.map {
+ mediaSessionManager.getActiveSessions(null)
+ },
mediaSessionManager.activeMediaChanges.filterNotNull(),
localBluetoothManager?.headsetAudioModeChanges?.map {
mediaSessionManager.getActiveSessions(null)
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
index b356f54..b4bd482 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
@@ -1703,6 +1703,30 @@
}
@Test
+ public void setName_memberDeviceNameIsSet() {
+ when(mDevice.getAlias()).thenReturn(DEVICE_NAME);
+ when(mSubDevice.getAlias()).thenReturn(DEVICE_NAME);
+
+ mCachedDevice.addMemberDevice(mSubCachedDevice);
+ mCachedDevice.setName(DEVICE_ALIAS);
+
+ verify(mDevice).setAlias(DEVICE_ALIAS);
+ verify(mSubDevice).setAlias(DEVICE_ALIAS);
+ }
+
+ @Test
+ public void setName_subDeviceNameIsSet() {
+ when(mDevice.getAlias()).thenReturn(DEVICE_NAME);
+ when(mSubDevice.getAlias()).thenReturn(DEVICE_NAME);
+
+ mCachedDevice.setSubDevice(mSubCachedDevice);
+ mCachedDevice.setName(DEVICE_ALIAS);
+
+ verify(mDevice).setAlias(DEVICE_ALIAS);
+ verify(mSubDevice).setAlias(DEVICE_ALIAS);
+ }
+
+ @Test
public void getProfileConnectionState_nullProfile_returnDisconnected() {
assertThat(mCachedDevice.getProfileConnectionState(null)).isEqualTo(
BluetoothProfile.STATE_DISCONNECTED);
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java
index aa5a298..4188d2e 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java
@@ -72,14 +72,18 @@
@Rule
public MockitoRule mMockitoRule = MockitoJUnit.rule();
- private final static long HISYNCID1 = 10;
- private final static long HISYNCID2 = 11;
- private final static String DEVICE_NAME_1 = "TestName_1";
- private final static String DEVICE_NAME_2 = "TestName_2";
- private final static String DEVICE_ALIAS_1 = "TestAlias_1";
- private final static String DEVICE_ALIAS_2 = "TestAlias_2";
- private final static String DEVICE_ADDRESS_1 = "AA:BB:CC:DD:EE:11";
- private final static String DEVICE_ADDRESS_2 = "AA:BB:CC:DD:EE:22";
+ private static final long HISYNCID1 = 10;
+ private static final long HISYNCID2 = 11;
+ private static final int GROUP_ID_1 = 20;
+ private static final int GROUP_ID_2 = 21;
+ private static final int PRESET_INDEX_1 = 1;
+ private static final int PRESET_INDEX_2 = 2;
+ private static final String DEVICE_NAME_1 = "TestName_1";
+ private static final String DEVICE_NAME_2 = "TestName_2";
+ private static final String DEVICE_ALIAS_1 = "TestAlias_1";
+ private static final String DEVICE_ALIAS_2 = "TestAlias_2";
+ private static final String DEVICE_ADDRESS_1 = "AA:BB:CC:DD:EE:11";
+ private static final String DEVICE_ADDRESS_2 = "AA:BB:CC:DD:EE:22";
private final BluetoothClass DEVICE_CLASS =
createBtClass(BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE);
private final Context mContext = ApplicationProvider.getApplicationContext();
@@ -295,6 +299,7 @@
mHearingAidDeviceManager.setSubDeviceIfNeeded(mCachedDevice2);
assertThat(mCachedDevice1.getSubDevice()).isEqualTo(mCachedDevice2);
+ verify(mDevice2).setAlias(DEVICE_ALIAS_1);
}
/**
@@ -706,14 +711,73 @@
}
@Test
- public void findMainDevice() {
+ public void findMainDevice_sameHiSyncId() {
when(mCachedDevice1.getHiSyncId()).thenReturn(HISYNCID1);
when(mCachedDevice2.getHiSyncId()).thenReturn(HISYNCID1);
mCachedDeviceManager.mCachedDevices.add(mCachedDevice1);
mCachedDevice1.setSubDevice(mCachedDevice2);
- assertThat(mHearingAidDeviceManager.findMainDevice(mCachedDevice2)).
- isEqualTo(mCachedDevice1);
+ assertThat(mHearingAidDeviceManager.findMainDevice(mCachedDevice2)).isEqualTo(
+ mCachedDevice1);
+ }
+
+ @Test
+ public void findMainDevice_sameGroupId() {
+ when(mCachedDevice1.getGroupId()).thenReturn(GROUP_ID_1);
+ when(mCachedDevice2.getGroupId()).thenReturn(GROUP_ID_2);
+ mCachedDeviceManager.mCachedDevices.add(mCachedDevice1);
+ mCachedDevice1.addMemberDevice(mCachedDevice2);
+
+ assertThat(mHearingAidDeviceManager.findMainDevice(mCachedDevice2)).isEqualTo(
+ mCachedDevice1);
+ }
+
+ @Test
+ public void syncDeviceWithinSet_synchronized_differentPresetIndex_shouldNotSync() {
+ when(mHapClientProfile.getActivePresetIndex(mDevice1)).thenReturn(PRESET_INDEX_1);
+ when(mHapClientProfile.getActivePresetIndex(mDevice2)).thenReturn(PRESET_INDEX_2);
+ when(mHapClientProfile.supportsSynchronizedPresets(mDevice1)).thenReturn(true);
+ when(mHapClientProfile.supportsSynchronizedPresets(mDevice2)).thenReturn(true);
+ when(mCachedDevice1.getGroupId()).thenReturn(GROUP_ID_1);
+ when(mCachedDevice2.getGroupId()).thenReturn(GROUP_ID_2);
+ mCachedDeviceManager.mCachedDevices.add(mCachedDevice1);
+ mCachedDevice1.addMemberDevice(mCachedDevice2);
+
+ mHearingAidDeviceManager.syncDeviceIfNeeded(mCachedDevice1);
+
+ verify(mHapClientProfile, never()).selectPreset(any(), anyInt());
+ }
+
+ @Test
+ public void syncDeviceWithinSet_unsynchronized_samePresetIndex_shouldNotSync() {
+ when(mHapClientProfile.getActivePresetIndex(mDevice1)).thenReturn(PRESET_INDEX_1);
+ when(mHapClientProfile.getActivePresetIndex(mDevice2)).thenReturn(PRESET_INDEX_1);
+ when(mHapClientProfile.supportsSynchronizedPresets(mDevice1)).thenReturn(false);
+ when(mHapClientProfile.supportsSynchronizedPresets(mDevice2)).thenReturn(false);
+ when(mCachedDevice1.getGroupId()).thenReturn(GROUP_ID_1);
+ when(mCachedDevice2.getGroupId()).thenReturn(GROUP_ID_2);
+ mCachedDeviceManager.mCachedDevices.add(mCachedDevice1);
+ mCachedDevice1.addMemberDevice(mCachedDevice2);
+
+ mHearingAidDeviceManager.syncDeviceIfNeeded(mCachedDevice1);
+
+ verify(mHapClientProfile, never()).selectPreset(any(), anyInt());
+ }
+
+ @Test
+ public void syncDeviceWithinSet_unsynchronized_differentPresetIndex_shouldSync() {
+ when(mHapClientProfile.getActivePresetIndex(mDevice1)).thenReturn(PRESET_INDEX_1);
+ when(mHapClientProfile.getActivePresetIndex(mDevice2)).thenReturn(PRESET_INDEX_2);
+ when(mHapClientProfile.supportsSynchronizedPresets(mDevice1)).thenReturn(false);
+ when(mHapClientProfile.supportsSynchronizedPresets(mDevice2)).thenReturn(false);
+ when(mCachedDevice1.getGroupId()).thenReturn(GROUP_ID_1);
+ when(mCachedDevice2.getGroupId()).thenReturn(GROUP_ID_2);
+ mCachedDeviceManager.mCachedDevices.add(mCachedDevice1);
+ mCachedDevice1.addMemberDevice(mCachedDevice2);
+
+ mHearingAidDeviceManager.syncDeviceIfNeeded(mCachedDevice2);
+
+ verify(mHapClientProfile).selectPreset(mDevice2, PRESET_INDEX_1);
}
private HearingAidInfo getLeftAshaHearingAidInfo(long hiSyncId) {
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidStatsLogUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidStatsLogUtilsTest.java
index bd5a022..cd16721 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidStatsLogUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidStatsLogUtilsTest.java
@@ -145,20 +145,29 @@
}
@Test
- public void getUserCategory_hearingDevicesUser() {
- prepareHearingDevicesUserHistory();
+ public void getUserCategory_hearableDevicesUser() {
+ prepareHearableDevicesUserHistory();
assertThat(HearingAidStatsLogUtils.getUserCategory(mContext)).isEqualTo(
- HearingAidStatsLogUtils.CATEGORY_HEARING_DEVICES);
+ HearingAidStatsLogUtils.CATEGORY_HEARABLE_DEVICES);
}
@Test
- public void getUserCategory_newHearingDevicesUser() {
- prepareHearingDevicesUserHistory();
+ public void getUserCategory_newHearableDevicesUser() {
+ prepareHearableDevicesUserHistory();
prepareNewUserHistory();
assertThat(HearingAidStatsLogUtils.getUserCategory(mContext)).isEqualTo(
- HearingAidStatsLogUtils.CATEGORY_NEW_HEARING_DEVICES);
+ HearingAidStatsLogUtils.CATEGORY_NEW_HEARABLE_DEVICES);
+ }
+
+ @Test
+ public void getUserCategory_bothHearingAidsAndHearableDevicesUser_returnHearingAidsUser() {
+ prepareHearingAidsUserHistory();
+ prepareHearableDevicesUserHistory();
+
+ assertThat(HearingAidStatsLogUtils.getUserCategory(mContext)).isEqualTo(
+ HearingAidStatsLogUtils.CATEGORY_HEARING_AIDS);
}
private long convertToStartOfDayTime(long timestamp) {
@@ -176,12 +185,12 @@
}
}
- private void prepareHearingDevicesUserHistory() {
+ private void prepareHearableDevicesUserHistory() {
final long todayStartOfDay = convertToStartOfDayTime(System.currentTimeMillis());
for (int i = CONNECTED_HISTORY_EXPIRED_DAY - 1; i >= 0; i--) {
final long data = todayStartOfDay - TimeUnit.DAYS.toMillis(i);
HearingAidStatsLogUtils.addToHistory(mContext,
- HearingAidStatsLogUtils.HistoryType.TYPE_HEARING_DEVICES_CONNECTED, data);
+ HearingAidStatsLogUtils.HistoryType.TYPE_HEARABLE_DEVICES_CONNECTED, data);
}
}
@@ -191,6 +200,6 @@
HearingAidStatsLogUtils.addToHistory(mContext,
HearingAidStatsLogUtils.HistoryType.TYPE_HEARING_AIDS_PAIRED, data);
HearingAidStatsLogUtils.addToHistory(mContext,
- HearingAidStatsLogUtils.HistoryType.TYPE_HEARING_DEVICES_PAIRED, data);
+ HearingAidStatsLogUtils.HistoryType.TYPE_HEARABLE_DEVICES_PAIRED, data);
}
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java
index cef0835..6ff90ba 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java
@@ -28,6 +28,7 @@
import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHapClient;
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothHearingAid;
import android.bluetooth.BluetoothPan;
@@ -55,7 +56,9 @@
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {ShadowBluetoothAdapter.class})
public class LocalBluetoothProfileManagerTest {
- private final static long HISYNCID = 10;
+ private static final long HISYNCID = 10;
+
+ private static final int GROUP_ID = 1;
@Mock
private LocalBluetoothManager mBtManager;
@Mock
@@ -201,7 +204,8 @@
* CachedBluetoothDeviceManager method
*/
@Test
- public void stateChangedHandler_receiveHAPConnectionStateChanged_shouldDispatchDeviceManager() {
+ public void
+ stateChangedHandler_receiveHearingAidConnectionStateChanged_dispatchDeviceManager() {
mShadowBluetoothAdapter.setSupportedProfiles(generateList(
new int[] {BluetoothProfile.HEARING_AID}));
mProfileManager.updateLocalProfiles();
@@ -219,6 +223,28 @@
}
/**
+ * Verify BluetoothHapClient.ACTION_HAP_CONNECTION_STATE_CHANGED with uuid intent will dispatch
+ * to {@link CachedBluetoothDeviceManager} method
+ */
+ @Test
+ public void stateChangedHandler_receiveHapClientConnectionStateChanged_dispatchDeviceManager() {
+ mShadowBluetoothAdapter.setSupportedProfiles(generateList(
+ new int[] {BluetoothProfile.HAP_CLIENT}));
+ mProfileManager.updateLocalProfiles();
+ when(mCachedBluetoothDevice.getGroupId()).thenReturn(GROUP_ID);
+
+ mIntent = new Intent(BluetoothHapClient.ACTION_HAP_CONNECTION_STATE_CHANGED);
+ mIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice);
+ mIntent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, BluetoothProfile.STATE_CONNECTING);
+ mIntent.putExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_CONNECTED);
+
+ mContext.sendBroadcast(mIntent);
+
+ verify(mDeviceManager).syncDeviceWithinHearingAidSetIfNeeded(mCachedBluetoothDevice,
+ BluetoothProfile.STATE_CONNECTED, BluetoothProfile.HAP_CLIENT);
+ }
+
+ /**
* Verify BluetoothPan.ACTION_CONNECTION_STATE_CHANGED intent with uuid will dispatch to
* profile connection state changed callback
*/
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index e2af631..fce7a00f 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -69,6 +69,219 @@
visibility: ["//visibility:private"],
}
+filegroup {
+ name: "SystemUI-tests-robofiles",
+ srcs: [
+ "tests/src/**/*.kt",
+ "tests/src/**/*.java",
+ ],
+ visibility: ["//visibility:private"],
+}
+
+// We are running robolectric tests in the tests directory as well as
+// multivalent tests. If you add a test, and it doesn't run in robolectric,
+// it should be added to this exclusion list. go/multivalent-tests
+filegroup {
+ name: "SystemUI-tests-broken-robofiles",
+ srcs: [
+ "tests/src/**/*DeviceOnlyTest.java",
+ "tests/src/**/*DeviceOnlyTest.kt",
+ "tests/src/**/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt",
+ "tests/src/**/systemui/accessibility/data/repository/AccessibilityQsShortcutsRepositoryImplForDeviceTest.kt",
+ "tests/src/**/systemui/biometrics/AuthDialogPanelInteractionDetectorTest.kt",
+ "tests/src/**/systemui/controls/management/ControlsFavoritingActivityTest.kt",
+ "tests/src/**/systemui/controls/management/ControlsProviderSelectorActivityTest.kt",
+ "tests/src/**/systemui/controls/start/ControlsStartableTest.kt",
+ "tests/src/**/systemui/haptics/slider/SliderStateTrackerTest.kt",
+ "tests/src/**/systemui/keyboard/stickykeys/ui/StickyKeysIndicatorCoordinatorTest.kt",
+ "tests/src/**/systemui/keyboard/stickykeys/ui/viewmodel/StickyKeysIndicatorViewModelTest.kt",
+ "tests/src/**/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceCoreStartableTest.kt",
+ "tests/src/**/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorParameterizedTest.kt",
+ "tests/src/**/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorSceneContainerTest.kt",
+ "tests/src/**/systemui/keyguard/ResourceTrimmerTest.kt",
+ "tests/src/**/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt",
+ "tests/src/**/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt",
+ "tests/src/**/systemui/media/controls/domain/pipeline/MediaTimeoutListenerTest.kt",
+ "tests/src/**/systemui/media/controls/ui/controller/MediaHierarchyManagerTest.kt",
+ "tests/src/**/systemui/mediaprojection/taskswitcher/MediaProjectionTaskSwitcherCoreStartableTest.kt",
+ "tests/src/**/systemui/media/taptotransfer/receiver/FakeMediaTttChipControllerReceiver.kt",
+ "tests/src/**/systemui/qs/tileimpl/QSTileViewImplTest.kt",
+ "tests/src/**/systemui/qs/tiles/DeviceControlsTileTest.kt",
+ "tests/src/**/systemui/screenshot/ActionExecutorTest.kt",
+ "tests/src/**/systemui/screenshot/ActionIntentCreatorTest.kt",
+ "tests/src/**/systemui/screenshot/DefaultScreenshotActionsProviderTest.kt",
+ "tests/src/**/systemui/screenshot/TakeScreenshotServiceTest.kt",
+ "tests/src/**/systemui/statusbar/commandline/CommandRegistryTest.kt",
+ "tests/src/**/systemui/statusbar/notification/collection/TargetSdkResolverTest.kt",
+ "tests/src/**/systemui/statusbar/notification/icon/IconManagerTest.kt",
+ "tests/src/**/systemui/statusbar/notification/row/BigPictureIconManagerTest.kt",
+ "tests/src/**/systemui/statusbar/notification/row/NotificationSettingsControllerTest.kt",
+ "tests/src/**/systemui/statusbar/notification/stack/ui/view/NotificationStatsLoggerTest.kt",
+ "tests/src/**/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImplTest.kt",
+ "tests/src/**/systemui/statusbar/policy/BatteryStateNotifierTest.kt",
+ "tests/src/**/systemui/statusbar/policy/FlashlightControllerImplTest.kt",
+ "tests/src/**/systemui/statusbar/policy/SensitiveNotificationProtectionControllerFlagDisabledTest.kt",
+ "tests/src/**/systemui/stylus/StylusUsiPowerStartableTest.kt",
+ "tests/src/**/systemui/temporarydisplay/TemporaryViewDisplayControllerTest.kt",
+ "tests/src/**/keyguard/ClockEventControllerTest.kt",
+ "tests/src/**/keyguard/LegacyLockIconViewControllerWithCoroutinesTest.kt",
+ "tests/src/**/keyguard/LegacyLockIconViewControllerBaseTest.kt",
+ "tests/src/**/keyguard/LegacyLockIconViewControllerTest.java",
+ "tests/src/**/systemui/animation/TransitionAnimatorTest.kt",
+ "tests/src/**/systemui/bluetooth/qsdialog/BluetoothAutoOnRepositoryTest.kt",
+ "tests/src/**/systemui/bluetooth/qsdialog/BluetoothStateInteractorTest.kt",
+ "tests/src/**/systemui/bluetooth/qsdialog/BluetoothTileDialogDelegateTest.kt",
+ "tests/src/**/systemui/bluetooth/qsdialog/BluetoothTileDialogRepositoryTest.kt",
+ "tests/src/**/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModelTest.kt",
+ "tests/src/**/systemui/bluetooth/qsdialog/DeviceItemFactoryTest.kt",
+ "tests/src/**/systemui/bluetooth/qsdialog/DeviceItemInteractorTest.kt",
+ "tests/src/**/systemui/broadcast/UserBroadcastDispatcherTest.kt",
+ "tests/src/**/systemui/charging/WiredChargingRippleControllerTest.kt",
+ "tests/src/**/systemui/clipboardoverlay/ClipboardModelTest.kt",
+ "tests/src/**/systemui/controls/controller/AuxiliaryPersistenceWrapperTest.kt",
+ "tests/src/**/systemui/controls/controller/ControlsBindingControllerImplTest.kt",
+ "tests/src/**/systemui/controls/controller/ControlsControllerImplTest.kt",
+ "tests/src/**/systemui/controls/controller/DeletionJobServiceTest.kt",
+ "tests/src/**/systemui/controls/settings/ControlsSettingsDialogManagerImplTest.kt",
+ "tests/src/**/systemui/controls/ui/ControlsUiControllerImplTest.kt",
+ "tests/src/**/systemui/controls/ui/ControlViewHolderTest.kt",
+ "tests/src/**/systemui/controls/ui/SelectionItemTest.kt",
+ "tests/src/**/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySectionTest.kt",
+ "tests/src/**/systemui/media/controls/domain/pipeline/LegacyMediaDataFilterImplTest.kt",
+ "tests/src/**/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImplTest.kt",
+ "tests/src/**/systemui/media/controls/domain/pipeline/MediaDataFilterImplTest.kt",
+ "tests/src/**/systemui/media/controls/ui/animation/AnimationBindHandlerTest.kt",
+ "tests/src/**/systemui/media/controls/ui/animation/ColorSchemeTransitionTest.kt",
+ "tests/src/**/systemui/media/controls/ui/animation/MetadataAnimationHandlerTest.kt",
+ "tests/src/**/systemui/media/controls/ui/controller/MediaCarouselControllerTest.kt",
+ "tests/src/**/systemui/media/controls/ui/controller/MediaControlPanelTest.kt",
+ "tests/src/**/systemui/media/controls/ui/controller/MediaViewControllerTest.kt",
+ "tests/src/**/systemui/media/controls/ui/drawable/SquigglyProgressTest.kt",
+ "tests/src/**/systemui/media/controls/ui/MediaPlayerDataTest.kt",
+ "tests/src/**/systemui/media/taptotransfer/sender/MediaTttSenderCoordinatorTest.kt",
+ "tests/src/**/systemui/navigationbar/gestural/BackPanelControllerTest.kt",
+ "tests/src/**/systemui/notetask/NoteTaskControllerTest.kt",
+ "tests/src/**/systemui/notetask/NoteTaskInitializerTest.kt",
+ "tests/src/**/systemui/power/domain/interactor/PowerInteractorTest.kt",
+ "tests/src/**/systemui/privacy/AppOpsPrivacyItemMonitorTest.kt",
+ "tests/src/**/systemui/privacy/PrivacyItemControllerTest.kt",
+ "tests/src/**/systemui/qs/external/CustomTileStatePersisterTest.kt",
+ "tests/src/**/systemui/qs/external/TileRequestDialogTest.kt",
+ "tests/src/**/systemui/qs/external/TileServiceRequestControllerTest.kt",
+ "tests/src/**/systemui/qs/tileimpl/TilesStatesTextTest.kt",
+ "tests/src/**/systemui/qs/tiles/AlarmTileTest.kt",
+ "tests/src/**/systemui/qs/tiles/BluetoothTileTest.kt",
+ "tests/src/**/systemui/screenshot/ScreenshotPolicyImplTest.kt",
+ "tests/src/**/systemui/settings/DisplayTrackerImplTest.kt",
+ "tests/src/**/systemui/settings/UserFileManagerImplTest.kt",
+ "tests/src/**/systemui/settings/UserTrackerImplReceiveTest.kt",
+ "tests/src/**/systemui/settings/UserTrackerImplTest.kt",
+ "tests/src/**/systemui/shade/GlanceableHubContainerControllerTest.kt",
+ "tests/src/**/systemui/shade/NotificationsQSContainerControllerLegacyTest.kt",
+ "tests/src/**/systemui/shade/NotificationsQSContainerControllerTest.kt",
+ "tests/src/**/systemui/shade/ShadeExpansionStateManagerTest.kt",
+ "tests/src/**/systemui/shade/ShadeHeaderControllerTest.kt",
+ "tests/src/**/systemui/shade/transition/LargeScreenShadeInterpolatorImplTest.kt",
+ "tests/src/**/systemui/statusbar/commandline/CommandParserTest.kt",
+ "tests/src/**/systemui/statusbar/connectivity/MobileStateTest.kt",
+ "tests/src/**/systemui/statusbar/events/SystemStatusAnimationSchedulerImplTest.kt",
+ "tests/src/**/systemui/statusbar/gesture/GenericGestureDetectorTest.kt",
+ "tests/src/**/systemui/statusbar/LightRevealScrimTest.kt",
+ "tests/src/**/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt",
+ "tests/src/**/systemui/statusbar/notification/collection/coordinator/DataStoreCoordinatorTest.kt",
+ "tests/src/**/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.kt",
+ "tests/src/**/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinatorTest.kt",
+ "tests/src/**/systemui/statusbar/notification/collection/coordinator/ShadeEventCoordinatorTest.kt",
+ "tests/src/**/systemui/statusbar/notification/collection/coordinator/StackCoordinatorTest.kt",
+ "tests/src/**/systemui/statusbar/notification/collection/coordinator/ViewConfigCoordinatorTest.kt",
+ "tests/src/**/systemui/statusbar/notification/logging/NotificationMemoryLoggerTest.kt",
+ "tests/src/**/systemui/statusbar/notification/logging/NotificationMemoryMeterTest.kt",
+ "tests/src/**/systemui/statusbar/notification/logging/NotificationMemoryViewWalkerTest.kt",
+ "tests/src/**/systemui/statusbar/notification/RoundableTest.kt",
+ "tests/src/**/systemui/statusbar/notification/row/ChannelEditorDialogControllerTest.kt",
+ "tests/src/**/systemui/statusbar/notification/row/SingleLineConversationViewBinderTest.kt",
+ "tests/src/**/systemui/statusbar/notification/row/SingleLineViewBinderTest.kt",
+ "tests/src/**/systemui/statusbar/notification/row/SingleLineViewInflaterTest.kt",
+ "tests/src/**/systemui/statusbar/notification/row/TextPrecomputerTest.kt",
+ "tests/src/**/systemui/statusbar/phone/FoldStateListenerTest.kt",
+ "tests/src/**/systemui/statusbar/phone/fragment/MultiSourceMinAlphaControllerTest.kt",
+ "tests/src/**/systemui/statusbar/pipeline/mobile/data/model/SystemUiCarrierConfigTest.kt",
+ "tests/src/**/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt",
+ "tests/src/**/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt",
+ "tests/src/**/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt",
+ "tests/src/**/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionTelephonySmokeTests.kt",
+ "tests/src/**/systemui/statusbar/pipeline/shared/data/repository/ConnectivityRepositoryImplTest.kt",
+ "tests/src/**/systemui/statusbar/pipeline/wifi/shared/model/WifiNetworkModelTest.kt",
+ "tests/src/**/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelIconParameterizedTest.kt",
+ "tests/src/**/systemui/statusbar/policy/DeviceControlsControllerImplTest.kt",
+ "tests/src/**/systemui/statusbar/policy/VariableDateViewControllerTest.kt",
+ "tests/src/**/systemui/statusbar/policy/WalletControllerImplTest.kt",
+ "tests/src/**/systemui/statusbar/SplitShadeLockScreenOverScrollerTest.kt",
+ "tests/src/**/systemui/stylus/StylusUsiPowerUiTest.kt",
+ "tests/src/**/systemui/temporarydisplay/chipbar/ChipbarCoordinatorTest.kt",
+ "tests/src/**/keyguard/KeyguardUpdateMonitorTest.java",
+ "tests/src/**/keyguard/LegacyLockIconViewControllerBaseTest.java",
+ "tests/src/**/keyguard/CarrierTextManagerTest.java",
+ "tests/src/**/systemui/ScreenDecorationsTest.java",
+ "tests/src/**/systemui/temporarydisplay/chipbar/SwipeChipbarAwayGestureHandlerTest.kt",
+ "tests/src/**/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt",
+ "tests/src/**/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImplTest.kt",
+ "tests/src/**/systemui/shared/system/RemoteTransitionTest.java",
+ "tests/src/**/systemui/navigationbar/NavigationBarControllerImplTest.java",
+ "tests/src/**/systemui/bluetooth/qsdialog/AudioSharingInteractorTest.kt",
+ "tests/src/**/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfigTest.kt",
+ "tests/src/**/systemui/notetask/LaunchNotesRoleSettingsTrampolineActivityTest.kt",
+ "tests/src/**/systemui/notetask/shortcut/LaunchNoteTaskActivityTest.kt",
+ "tests/src/**/systemui/DisplayCutoutBaseViewTest.kt",
+ "tests/src/**/systemui/qs/tiles/dialog/InternetDialogDelegateTest.java",
+ "tests/src/**/systemui/qs/tiles/dialog/InternetDialogDelegateControllerTest.java",
+ "tests/src/**/systemui/qs/tiles/HotspotTileTest.java",
+ "tests/src/**/systemui/qs/external/TileLifecycleManagerTest.java",
+ "tests/src/**/systemui/recents/OverviewProxyServiceTest.kt",
+ "tests/src/**/systemui/stylus/StylusManagerTest.kt",
+ "tests/src/**/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java",
+ "tests/src/**/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java",
+ "tests/src/**/systemui/statusbar/policy/BatteryControllerStartableTest.java",
+ "tests/src/**/systemui/statusbar/policy/BatteryControllerTest.java",
+ "tests/src/**/systemui/statusbar/policy/SensitiveNotificationProtectionControllerTest.kt",
+ "tests/src/**/systemui/statusbar/notification/NotificationSectionsFeatureManagerTest.kt",
+ "tests/src/**/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepositoryTest.kt",
+ "tests/src/**/systemui/statusbar/KeyboardShortcutsReceiverTest.java",
+ "tests/src/**/systemui/wmshell/BubblesTest.java",
+ "tests/src/**/systemui/biometrics/AuthRippleControllerTest.kt",
+ "tests/src/**/keyguard/KeyguardAbsKeyInputViewControllerTest.java",
+ "tests/src/**/systemui/accessibility/floatingmenu/MenuAnimationControllerTest.java",
+ "tests/src/**/systemui/clipboardoverlay/ClipboardListenerTest.java",
+ "tests/src/**/systemui/doze/DozeScreenStateTest.java",
+ "tests/src/**/systemui/keyguard/WorkLockActivityControllerTest.java",
+ "tests/src/**/systemui/media/dialog/MediaOutputControllerTest.java",
+ "tests/src/**/systemui/navigationbar/NavigationBarTest.java",
+ "tests/src/**/systemui/power/PowerNotificationWarningsTest.java",
+ "tests/src/**/systemui/power/PowerUITest.java",
+ "tests/src/**/systemui/qs/QSFooterViewControllerTest.java",
+ "tests/src/**/systemui/qs/QSImplTest.java",
+ "tests/src/**/systemui/qs/QSSecurityFooterTest.java",
+ "tests/src/**/systemui/qs/tileimpl/QSTileImplTest.java",
+ "tests/src/**/systemui/qs/tiles/QuickAccessWalletTileTest.java",
+ "tests/src/**/systemui/shade/carrier/ShadeCarrierGroupControllerTest.java",
+ "tests/src/**/systemui/shared/plugins/PluginActionManagerTest.java",
+ "tests/src/**/systemui/statusbar/CommandQueueTest.java",
+ "tests/src/**/systemui/statusbar/connectivity/CallbackHandlerTest.java",
+ "tests/src/**/systemui/statusbar/connectivity/NetworkControllerBaseTest.java",
+ "tests/src/**/systemui/statusbar/KeyguardIndicationControllerTest.java",
+ "tests/src/**/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java",
+ "tests/src/**/systemui/statusbar/phone/ScrimControllerTest.java",
+ "tests/src/**/systemui/statusbar/policy/RotationLockControllerImplTest.java",
+ "tests/src/**/systemui/statusbar/policy/SecurityControllerTest.java",
+ "tests/src/**/systemui/toast/ToastUITest.java",
+ "tests/src/**/systemui/statusbar/connectivity/NetworkControllerDataTest.java",
+ "tests/src/**/systemui/statusbar/connectivity/NetworkControllerEthernetTest.java",
+ "tests/src/**/systemui/statusbar/connectivity/NetworkControllerSignalTest.java",
+ "tests/src/**/systemui/statusbar/connectivity/NetworkControllerWifiTest.java",
+ ],
+ visibility: ["//visibility:private"],
+}
+
//Create a library to expose SystemUI's resources to other modules.
android_library {
name: "SystemUI-res",
@@ -169,6 +382,7 @@
"androidx.compose.material_material-icons-extended",
"androidx.activity_activity-compose",
"androidx.compose.animation_animation-graphics",
+ "device_policy_aconfig_flags_lib",
],
libs: [
"keepanno-annotations",
@@ -409,6 +623,7 @@
"//frameworks/libs/systemui:compilelib",
"SystemUI-tests-base",
"androidx.compose.runtime_runtime",
+ "SystemUI-core",
],
libs: [
"keepanno-annotations",
@@ -433,6 +648,21 @@
plugins: ["dagger2-compiler"],
}
+java_library {
+ name: "RoboTestLibraries",
+ static_libs: [
+ "dagger2",
+ "androidx.test.uiautomator_uiautomator",
+ "androidx.core_core-animation-testing",
+ "androidx.test.ext.junit",
+ "inline-mockito-robolectric-prebuilt",
+ "platform-parametric-runner-lib",
+ "SystemUICustomizationTestUtils",
+ "kotlin-test",
+ "kosmos",
+ ],
+}
+
android_robolectric_test {
name: "SystemUiRoboTests",
srcs: [
@@ -442,14 +672,40 @@
":SystemUI-tests-multivalent",
],
static_libs: [
- "dagger2",
- "androidx.test.uiautomator_uiautomator",
- "androidx.core_core-animation-testing",
- "androidx.test.ext.junit",
- "inline-mockito-robolectric-prebuilt",
- "platform-parametric-runner-lib",
- "SystemUICustomizationTestUtils",
- "kosmos",
+ "RoboTestLibraries",
+ ],
+ libs: [
+ "android.test.runner",
+ "android.test.base",
+ "android.test.mock",
+ "truth",
+ ],
+
+ upstream: true,
+
+ instrumentation_for: "SystemUIRobo-stub",
+ java_resource_dirs: ["tests/robolectric/config"],
+ plugins: [
+ "dagger2-compiler",
+ ],
+}
+
+// in-place tests which use Robolectric in the tests directory
+// instead of multivalentTests
+android_robolectric_test {
+ name: "SystemUiRoboTestsInplace",
+ srcs: [
+ "tests/robolectric/src/**/*.kt",
+ "tests/robolectric/src/**/*.java",
+ ":SystemUI-tests-utils",
+ ":SystemUI-tests-multivalent",
+ ":SystemUI-tests-robofiles",
+ ],
+ exclude_srcs: [
+ ":SystemUI-tests-broken-robofiles",
+ ],
+ static_libs: [
+ "RoboTestLibraries",
],
libs: [
"android.test.runner",
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 59e2b91..b9e70ef 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -1110,7 +1110,7 @@
android:resource="@xml/home_controls_dream_metadata" />
</service>
- <activity android:name="com.android.systemui.keyboard.shortcut.ShortcutHelperActivity"
+ <activity android:name="com.android.systemui.keyboard.shortcut.ui.view.ShortcutHelperActivity"
android:exported="false"
android:theme="@style/ShortcutHelperTheme"
android:excludeFromRecents="true"
diff --git a/packages/SystemUI/OWNERS b/packages/SystemUI/OWNERS
index 796e391..d2e5a13 100644
--- a/packages/SystemUI/OWNERS
+++ b/packages/SystemUI/OWNERS
@@ -4,13 +4,13 @@
dsandler@android.com
-aaronjli@google.com
achalke@google.com
acul@google.com
adamcohen@google.com
aioana@google.com
alexflo@google.com
andonian@google.com
+amiko@google.com
aroederer@google.com
arteiro@google.com
asc@google.com
@@ -39,7 +39,6 @@
hyunyoungs@google.com
ikateryna@google.com
iyz@google.com
-jamesoleary@google.com
jbolinger@google.com
jdemeulenaere@google.com
jeffdq@google.com
@@ -82,6 +81,7 @@
pomini@google.com
princedonkor@google.com
rahulbanerjee@google.com
+rgl@google.com
roosa@google.com
saff@google.com
santie@google.com
@@ -110,6 +110,3 @@
yuandizhou@google.com
yurilin@google.com
zakcohen@google.com
-
-#Android TV
-rgl@google.com
diff --git a/packages/SystemUI/TEST_MAPPING b/packages/SystemUI/TEST_MAPPING
index 0c89a5d..deab818 100644
--- a/packages/SystemUI/TEST_MAPPING
+++ b/packages/SystemUI/TEST_MAPPING
@@ -59,13 +59,16 @@
]
}
],
-
+
"auto-end-to-end-postsubmit": [
{
"name": "AndroidAutomotiveHomeTests",
"options" : [
{
"include-filter": "android.platform.tests.HomeTest"
+ },
+ {
+ "exclude-filter": "android.platform.tests.HomeTest#testAssistantWidget"
}
]
},
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values-cs/strings.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values-cs/strings.xml
index 15eb928..be1916f 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/values-cs/strings.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values-cs/strings.xml
@@ -2,7 +2,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="accessibility_menu_service_name" msgid="730136711554740131">"Nabídka usnadnění přístupu"</string>
- <string name="accessibility_menu_intro" msgid="3164193281544042394">"Nabídka usnadnění přístupu zobrazuje na obrazovce velkou nabídku k ovládání zařízení. Můžete zamknout zařízení, upravit hlasitost a jas, pořídit snímek obrazovky apod."</string>
+ <string name="accessibility_menu_intro" msgid="3164193281544042394">"Nabídka usnadnění přístupu zobrazuje na obrazovce velkou nabídku k ovládání zařízení – například k jeho zamknutí, úpravě hlasitosti a jasu, pořízení snímku obrazovky apod."</string>
<string name="assistant_label" msgid="6796392082252272356">"Asistent"</string>
<string name="assistant_utterance" msgid="65509599221141377">"Asistent"</string>
<string name="a11y_settings_label" msgid="3977714687248445050">"Nastavení usnadnění přístupu"</string>
@@ -20,7 +20,7 @@
<string name="brightness_down_label" msgid="7115662941913272072">"Snížit jas"</string>
<string name="previous_button_content_description" msgid="840869171117765966">"Zpět na předchozí obrazovku"</string>
<string name="next_button_content_description" msgid="6810058269847364406">"Přejít na další obrazovku"</string>
- <string name="accessibility_menu_description" msgid="4458354794093858297">"Nabídka usnadnění přístupu zobrazuje na obrazovce velkou nabídku k ovládání zařízení. Můžete zamknout zařízení, upravit hlasitost a jas, pořídit snímek obrazovky apod."</string>
+ <string name="accessibility_menu_description" msgid="4458354794093858297">"Nabídka usnadnění přístupu zobrazuje na obrazovce velkou nabídku k ovládání zařízení – například k jeho zamknutí, úpravě hlasitosti a jasu, pořízení snímku obrazovky apod."</string>
<string name="accessibility_menu_summary" msgid="340071398148208130">"Ovládání zařízení pomocí velké nabídky"</string>
<string name="accessibility_menu_settings_name" msgid="1716888058785672611">"Nastavení nabídky usnadnění přístupu"</string>
<string name="accessibility_menu_large_buttons_title" msgid="8978499601044961736">"Velká tlačítka"</string>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values-es/strings.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values-es/strings.xml
index 877a43c..b97df64 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/values-es/strings.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values-es/strings.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="accessibility_menu_service_name" msgid="730136711554740131">"Menú Accesibilidad"</string>
+ <string name="accessibility_menu_service_name" msgid="730136711554740131">"Menú de accesibilidad"</string>
<string name="accessibility_menu_intro" msgid="3164193281544042394">"El menú de accesibilidad es un menú de gran tamaño que se muestra en pantalla para controlar tu dispositivo. Puedes bloquear el dispositivo, controlar el volumen y el brillo, hacer capturas de pantalla y más."</string>
<string name="assistant_label" msgid="6796392082252272356">"Asistente"</string>
<string name="assistant_utterance" msgid="65509599221141377">"Asistente"</string>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values-eu/strings.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values-eu/strings.xml
index b314c8e..1e21c775 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/values-eu/strings.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values-eu/strings.xml
@@ -20,7 +20,7 @@
<string name="brightness_down_label" msgid="7115662941913272072">"Txikitu distira"</string>
<string name="previous_button_content_description" msgid="840869171117765966">"Joan aurreko pantailara"</string>
<string name="next_button_content_description" msgid="6810058269847364406">"Joan hurrengo pantailara"</string>
- <string name="accessibility_menu_description" msgid="4458354794093858297">"Erabilerraztasun-menuari esker, tamaina handiko menu bat izango duzu pantailan; menu horren bidez, gailua kontrolatzeko aukera izango duzu. Besteak beste, hauek egin ahalko dituzu: gailua blokeatu; bolumena eta distira kontrolatu, eta pantaila-argazkiak egin."</string>
+ <string name="accessibility_menu_description" msgid="4458354794093858297">"Erabilerraztasun-menuari esker, tamaina handiko menu bat izango duzu pantailan; menu horren bidez, gailua kontrolatzeko aukera izango duzu. Besteak beste, hauek egin ahalko dituzu: gailua blokeatu, bolumena eta distira kontrolatu, eta pantaila-argazkiak egin."</string>
<string name="accessibility_menu_summary" msgid="340071398148208130">"Kontrolatu gailua menu handiaren bidez"</string>
<string name="accessibility_menu_settings_name" msgid="1716888058785672611">"Erabilerraztasun-menuaren ezarpenak"</string>
<string name="accessibility_menu_large_buttons_title" msgid="8978499601044961736">"Botoi handiak"</string>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values-hr/strings.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values-hr/strings.xml
index eff6cb4..5c3c99c 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/values-hr/strings.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values-hr/strings.xml
@@ -2,7 +2,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="accessibility_menu_service_name" msgid="730136711554740131">"Izbornik pristupačnosti"</string>
- <string name="accessibility_menu_intro" msgid="3164193281544042394">"Izbornik pristupačnosti veliki je zaslonski izbornik koji vam omogućuje upravljanje uređajem. Putem ovog izbornika možete zaključati uređaj, upravljati glasnoćom i svjetlinom, izrađivati snimke zaslona i drugo."</string>
+ <string name="accessibility_menu_intro" msgid="3164193281544042394">"Izbornik pristupačnosti veliki je zaslonski izbornik koji vam omogućuje upravljanje uređajem. Putem njega možete zaključati uređaj, upravljati glasnoćom i svjetlinom, izrađivati snimke zaslona i drugo."</string>
<string name="assistant_label" msgid="6796392082252272356">"Asistent"</string>
<string name="assistant_utterance" msgid="65509599221141377">"Asistent"</string>
<string name="a11y_settings_label" msgid="3977714687248445050">"Postavke pristupačnosti"</string>
@@ -20,7 +20,7 @@
<string name="brightness_down_label" msgid="7115662941913272072">"Smanji svjetlinu"</string>
<string name="previous_button_content_description" msgid="840869171117765966">"Idi na prethodni zaslon"</string>
<string name="next_button_content_description" msgid="6810058269847364406">"Idi na sljedeći zaslon"</string>
- <string name="accessibility_menu_description" msgid="4458354794093858297">"Izbornik pristupačnosti pruža velik izbornik na zaslonu u svrhu upravljanja uređajem. Možete zaključati uređaj, upravljati glasnoćom i svjetlinom, izrađivati snimke zaslona i drugo."</string>
+ <string name="accessibility_menu_description" msgid="4458354794093858297">"Izbornik pristupačnosti veliki je zaslonski izbornik koji vam omogućuje upravljanje uređajem. Putem njega možete zaključati uređaj, upravljati glasnoćom i svjetlinom, izrađivati snimke zaslona i drugo."</string>
<string name="accessibility_menu_summary" msgid="340071398148208130">"Upravljanje uređajem pomoću velikog izbornika"</string>
<string name="accessibility_menu_settings_name" msgid="1716888058785672611">"Postavke izbornika pristupačnosti"</string>
<string name="accessibility_menu_large_buttons_title" msgid="8978499601044961736">"Veliki gumbi"</string>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values-tr/strings.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values-tr/strings.xml
index 38cc395..d23ddca 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/values-tr/strings.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values-tr/strings.xml
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="accessibility_menu_service_name" msgid="730136711554740131">"Erişilebilirlik menüsü"</string>
- <string name="accessibility_menu_intro" msgid="3164193281544042394">"Erişilebilirlik menüsü, cihazınızı kontrol etmeniz için geniş bir ekran menüsü sağlar. Cihazınızı kilitleyebilir, ses düzeyini ve parlaklığı kontrol edebilir, ekran görüntüsü alabilir ve daha fazlasını yapabilirsiniz."</string>
+ <string name="accessibility_menu_service_name" msgid="730136711554740131">"Erişilebilirlik Menüsü"</string>
+ <string name="accessibility_menu_intro" msgid="3164193281544042394">"Erişilebilirlik Menüsü, cihazınızı kontrol etmeniz için geniş bir ekran menüsü sağlar. Cihazınızı kilitleyebilir, ses düzeyini ve parlaklığı kontrol edebilir, ekran görüntüsü alabilir ve daha fazlasını yapabilirsiniz."</string>
<string name="assistant_label" msgid="6796392082252272356">"Asistan"</string>
<string name="assistant_utterance" msgid="65509599221141377">"Asistan"</string>
<string name="a11y_settings_label" msgid="3977714687248445050">"Erişebilirlik Ayarları"</string>
@@ -20,7 +20,7 @@
<string name="brightness_down_label" msgid="7115662941913272072">"Parlaklığı azalt"</string>
<string name="previous_button_content_description" msgid="840869171117765966">"Önceki ekrana git"</string>
<string name="next_button_content_description" msgid="6810058269847364406">"Sonraki ekrana git"</string>
- <string name="accessibility_menu_description" msgid="4458354794093858297">"Erişilebilirlik menüsü, cihazınızı kontrol etmeniz için geniş bir ekran menüsü sağlar. Cihazınızı kilitleyebilir, ses düzeyini ve parlaklığı kontrol edebilir, ekran görüntüsü alabilir ve daha fazlasını yapabilirsiniz."</string>
+ <string name="accessibility_menu_description" msgid="4458354794093858297">"Erişilebilirlik Menüsü, cihazınızı kontrol etmeniz için geniş bir ekran menüsü sağlar. Cihazınızı kilitleyebilir, ses düzeyini ve parlaklığı kontrol edebilir, ekran görüntüsü alabilir ve daha fazlasını yapabilirsiniz."</string>
<string name="accessibility_menu_summary" msgid="340071398148208130">"Cihazı geniş menüyle kontrol edin"</string>
<string name="accessibility_menu_settings_name" msgid="1716888058785672611">"Erişilebilirlik Menüsü Ayarları"</string>
<string name="accessibility_menu_large_buttons_title" msgid="8978499601044961736">"Büyük düğmeler"</string>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/tests/src/com/android/systemui/accessibility/accessibilitymenu/tests/AccessibilityMenuServiceTest.java b/packages/SystemUI/accessibility/accessibilitymenu/tests/src/com/android/systemui/accessibility/accessibilitymenu/tests/AccessibilityMenuServiceTest.java
index 66943d4..991ce12 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/tests/src/com/android/systemui/accessibility/accessibilitymenu/tests/AccessibilityMenuServiceTest.java
+++ b/packages/SystemUI/accessibility/accessibilitymenu/tests/src/com/android/systemui/accessibility/accessibilitymenu/tests/AccessibilityMenuServiceTest.java
@@ -30,7 +30,7 @@
import static com.android.systemui.accessibility.accessibilitymenu.AccessibilityMenuService.INTENT_TOGGLE_MENU;
import static com.android.systemui.accessibility.accessibilitymenu.AccessibilityMenuService.PACKAGE_NAME;
-import static com.google.common.truth.Truth.assertWithMessage;
+import static com.google.common.truth.Truth.assertThat;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.app.Instrumentation;
@@ -45,11 +45,11 @@
import android.hardware.display.DisplayManager;
import android.media.AudioManager;
import android.os.PowerManager;
-import android.os.RemoteException;
import android.platform.uiautomator_helpers.WaitUtils;
import android.provider.Settings;
import android.util.Log;
import android.view.Display;
+import android.view.KeyEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
@@ -69,6 +69,7 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.io.IOException;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
@@ -88,6 +89,7 @@
private static Instrumentation sInstrumentation;
private static UiAutomation sUiAutomation;
private static UiDevice sUiDevice;
+ private static String sLockSettings;
private static final AtomicInteger sLastGlobalAction = new AtomicInteger(NO_GLOBAL_ACTION);
private static final AtomicBoolean sOpenBlocked = new AtomicBoolean(false);
@@ -106,12 +108,18 @@
sUiAutomation.adoptShellPermissionIdentity(
UiAutomation.ALL_PERMISSIONS.toArray(new String[0]));
sUiDevice = UiDevice.getInstance(sInstrumentation);
+ sLockSettings = sUiDevice.executeShellCommand("locksettings get-disabled");
+ Log.i(TAG, "locksettings get-disabled returns " + sLockSettings);
+ // Some test in the test class requires the device to be in lock screen
+ // ensure we have locksettings enabled before running the tests
+ sUiDevice.executeShellCommand("locksettings set-disabled false");
final Context context = sInstrumentation.getTargetContext();
sAccessibilityManager = context.getSystemService(AccessibilityManager.class);
sPowerManager = context.getSystemService(PowerManager.class);
sKeyguardManager = context.getSystemService(KeyguardManager.class);
sDisplayManager = context.getSystemService(DisplayManager.class);
+ unlockSignal();
// Disable all a11yServices if any are active.
if (!sAccessibilityManager.getEnabledAccessibilityServiceList(
@@ -154,9 +162,10 @@
}
@AfterClass
- public static void classTeardown() {
+ public static void classTeardown() throws IOException {
Settings.Secure.putString(sInstrumentation.getTargetContext().getContentResolver(),
Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, "");
+ sUiDevice.executeShellCommand("locksettings set-disabled " + sLockSettings);
}
@Before
@@ -176,28 +185,32 @@
}
private static boolean isMenuVisible() {
+ sUiDevice.waitForIdle();
AccessibilityNodeInfo root = sUiAutomation.getRootInActiveWindow();
return root != null && root.getPackageName().toString().equals(PACKAGE_NAME);
}
- private static void wakeUpScreen() throws RemoteException {
- sUiDevice.wakeUp();
+ private static void wakeUpScreen() {
+ sUiDevice.pressKeyCode(KeyEvent.KEYCODE_WAKEUP);
WaitUtils.waitForValueToSettle("Screen On", AccessibilityMenuServiceTest::isScreenOn);
- assertWithMessage("Screen is on").that(isScreenOn()).isTrue();
+ WaitUtils.ensureThat("Screen is on", AccessibilityMenuServiceTest::isScreenOn);
}
- private static void closeScreen() throws Throwable {
- sUiAutomation.performGlobalAction(GLOBAL_ACTION_LOCK_SCREEN);
+ private static void closeScreen() {
+ // go/adb-cheats#lock-screen
+ sUiDevice.pressKeyCode(KeyEvent.KEYCODE_SLEEP);
WaitUtils.waitForValueToSettle("Screen Off", AccessibilityMenuServiceTest::isScreenOff);
- assertWithMessage("Screen is off").that(isScreenOff()).isTrue();
+ WaitUtils.ensureThat("Screen is off", AccessibilityMenuServiceTest::isScreenOff);
+ WaitUtils.ensureThat(
+ "Screen is locked", () -> sKeyguardManager.isKeyguardLocked());
}
private static void openMenu() throws Throwable {
unlockSignal();
if (!isMenuVisible()) {
sInstrumentation.getTargetContext().sendBroadcast(INTENT_OPEN_MENU);
- sUiDevice.waitForIdle();
- WaitUtils.ensureThat("Accessibility Menu is visible", () -> isMenuVisible());
+ WaitUtils.ensureThat("Accessibility Menu is visible",
+ AccessibilityMenuServiceTest::isMenuVisible);
}
}
@@ -449,6 +462,7 @@
openMenu();
closeScreen();
wakeUpScreen();
+ assertThat(sKeyguardManager.isKeyguardLocked()).isTrue();
TestUtils.waitUntil("Menu did not close.",
TIMEOUT_UI_CHANGE_S,
@@ -460,6 +474,8 @@
public void testOnScreenLock_cannotOpenMenu() throws Throwable {
closeScreen();
wakeUpScreen();
+ assertThat(sKeyguardManager.isKeyguardLocked()).isTrue();
+
sInstrumentation.getContext().sendBroadcast(INTENT_OPEN_MENU);
sUiDevice.waitForIdle();
@@ -468,10 +484,7 @@
sOpenBlocked::get);
}
- private static void unlockSignal() throws RemoteException {
- if (!sKeyguardManager.isKeyguardLocked()) {
- return;
- }
+ private static void unlockSignal() throws IOException {
// go/adb-cheats#unlock-screen
wakeUpScreen();
if (sKeyguardManager.isKeyguardLocked()) {
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index b3aa7e1..21881f6 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -26,13 +26,6 @@
}
flag {
- name: "refactor_keyguard_dismiss_intent"
- namespace: "systemui"
- description: "Update how keyguard dismiss intents are stored."
- bug: "275069969"
-}
-
-flag {
name: "notification_heads_up_cycling"
namespace: "systemui"
@@ -178,16 +171,6 @@
}
flag {
- name: "nssl_falsing_fix"
- namespace: "systemui"
- description: "Minor touch changes to prevent falsing errors in NSSL"
- bug: "316551193"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-
-flag {
name: "refactor_get_current_user"
namespace: "systemui"
description: "KeyguardUpdateMonitor.getCurrentUser() was providing outdated results."
@@ -372,13 +355,6 @@
}
flag {
- name: "media_in_scene_container"
- namespace: "systemui"
- description: "Enable media in the scene container framework"
- bug: "296122467"
-}
-
-flag {
name: "pss_task_switcher"
namespace: "systemui"
description: "Enable the task switcher feature for partial screen sharing"
@@ -595,6 +571,16 @@
}
flag {
+ name: "contextual_tips_assistant_dismiss_fix"
+ namespace: "systemui"
+ description: "Improve assistant dismiss signal accuracy for contextual tips."
+ bug: "334759504"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
name: "shaderlib_loading_effect_refactor"
namespace: "systemui"
description: "Extend shader library to provide the common loading effects."
@@ -810,7 +796,17 @@
name: "dream_input_session_pilfer_once"
namespace: "systemui"
description: "Pilfer at most once per input session"
- bug: "324600132"
+ bug: "333596426"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
+ name: "shade_collapse_activity_launch_fix"
+ namespace: "systemui"
+ description: "Avoid collapsing the shade on activity launch if it is already collapsed, as this causes a flicker."
+ bug: "331591373"
metadata {
purpose: PURPOSE_BUGFIX
}
@@ -852,3 +848,13 @@
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "communal_bouncer_do_not_modify_plugin_open"
+ namespace: "systemui"
+ description: "do not modify notification shade when handling bouncer expansion."
+ bug: "338252661"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewTransitionAnimatorController.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewTransitionAnimatorController.kt
index 9ad0fc5..fd79f62 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewTransitionAnimatorController.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewTransitionAnimatorController.kt
@@ -191,14 +191,20 @@
// so we have to take the optical insets into account.
ghostedView.getLocationOnScreen(ghostedViewLocation)
val insets = backgroundInsets
- state.top = ghostedViewLocation[1] + insets.top
+ val boundCorrections: Rect =
+ if (ghostedView is LaunchableView) {
+ ghostedView.getPaddingForLaunchAnimation()
+ } else {
+ Rect()
+ }
+ state.top = ghostedViewLocation[1] + insets.top + boundCorrections.top
state.bottom =
ghostedViewLocation[1] + (ghostedView.height * ghostedView.scaleY).roundToInt() -
- insets.bottom
- state.left = ghostedViewLocation[0] + insets.left
+ insets.bottom + boundCorrections.bottom
+ state.left = ghostedViewLocation[0] + insets.left + boundCorrections.left
state.right =
ghostedViewLocation[0] + (ghostedView.width * ghostedView.scaleX).roundToInt() -
- insets.right
+ insets.right + boundCorrections.right
}
override fun onTransitionAnimationStart(isExpandingFullyAbove: Boolean) {
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt
index da6ccaa..330ab0f 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt
@@ -16,6 +16,7 @@
package com.android.systemui.animation
+import android.graphics.Rect
import android.view.View
/** A view that can expand/launch into an app or a dialog. */
@@ -41,6 +42,9 @@
/** Perform an action when the activity launch animation ends */
fun onActivityLaunchAnimationEnd() {}
+
+ /** Provide an optional correction applied to the visible area during a launch animation */
+ fun getPaddingForLaunchAnimation(): Rect = Rect()
}
/** A delegate that can be used by views to make the implementation of [LaunchableView] easier. */
diff --git a/packages/SystemUI/checks/Android.bp b/packages/SystemUI/checks/Android.bp
index addcaf4..04ac748 100644
--- a/packages/SystemUI/checks/Android.bp
+++ b/packages/SystemUI/checks/Android.bp
@@ -38,8 +38,9 @@
defaults: ["AndroidLintCheckerTestDefaults"],
srcs: ["tests/**/*.kt"],
data: [
- ":framework",
":androidx.annotation_annotation",
+ ":dagger2",
+ ":framework",
":kotlinx-coroutines-core",
],
static_libs: [
diff --git a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SingletonAndroidComponentDetector.kt b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SingletonAndroidComponentDetector.kt
new file mode 100644
index 0000000..68ec1ee
--- /dev/null
+++ b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SingletonAndroidComponentDetector.kt
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.systemui.lint
+
+import com.android.tools.lint.detector.api.AnnotationInfo
+import com.android.tools.lint.detector.api.AnnotationUsageInfo
+import com.android.tools.lint.detector.api.AnnotationUsageType
+import com.android.tools.lint.detector.api.Category
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Implementation
+import com.android.tools.lint.detector.api.Issue
+import com.android.tools.lint.detector.api.JavaContext
+import com.android.tools.lint.detector.api.Scope
+import com.android.tools.lint.detector.api.Severity
+import com.android.tools.lint.detector.api.SourceCodeScanner
+import org.jetbrains.uast.UAnnotation
+import org.jetbrains.uast.UClass
+import org.jetbrains.uast.UElement
+import org.jetbrains.uast.UMethod
+
+/**
+ * Prevents binding Activities, Services, and BroadcastReceivers as Singletons in the Dagger graph.
+ *
+ * It is OK to mark a BroadcastReceiver as singleton as long as it is being constructed/injected and
+ * registered directly in the code. If instead it is declared in the manifest, and we let Android
+ * construct it for us, we also need to let Android destroy it for us, so don't allow marking it as
+ * singleton.
+ */
+class SingletonAndroidComponentDetector : Detector(), SourceCodeScanner {
+ override fun applicableAnnotations(): List<String> {
+ return listOf(
+ "com.android.systemui.dagger.SysUISingleton",
+ )
+ }
+
+ override fun isApplicableAnnotationUsage(type: AnnotationUsageType): Boolean =
+ type == AnnotationUsageType.DEFINITION
+
+ override fun visitAnnotationUsage(
+ context: JavaContext,
+ element: UElement,
+ annotationInfo: AnnotationInfo,
+ usageInfo: AnnotationUsageInfo
+ ) {
+ if (element !is UAnnotation) {
+ return
+ }
+
+ val parent = element.uastParent ?: return
+
+ if (isInvalidBindingMethod(parent)) {
+ context.report(
+ ISSUE,
+ element,
+ context.getLocation(element),
+ "Do not bind Activities, Services, or BroadcastReceivers as Singleton."
+ )
+ } else if (isInvalidClassDeclaration(parent)) {
+ context.report(
+ ISSUE,
+ element,
+ context.getLocation(element),
+ "Do not mark Activities or Services as Singleton."
+ )
+ }
+ }
+
+ private fun isInvalidBindingMethod(parent: UElement): Boolean {
+ if (parent !is UMethod) {
+ return false
+ }
+
+ if (
+ parent.returnType?.canonicalText !in
+ listOf(
+ "android.app.Activity",
+ "android.app.Service",
+ "android.content.BroadcastReceiver",
+ )
+ ) {
+ return false
+ }
+
+ if (
+ !MULTIBIND_ANNOTATIONS.all { it in parent.annotations.map { it.qualifiedName } } &&
+ !MULTIPROVIDE_ANNOTATIONS.all { it in parent.annotations.map { it.qualifiedName } }
+ ) {
+ return false
+ }
+ return true
+ }
+
+ private fun isInvalidClassDeclaration(parent: UElement): Boolean {
+ if (parent !is UClass) {
+ return false
+ }
+
+ if (
+ parent.javaPsi.superClass?.qualifiedName !in
+ listOf(
+ "android.app.Activity",
+ "android.app.Service",
+ // Fine to mark BroadcastReceiver as singleton in this scenario
+ )
+ ) {
+ return false
+ }
+
+ return true
+ }
+
+ companion object {
+ @JvmField
+ val ISSUE: Issue =
+ Issue.create(
+ id = "SingletonAndroidComponent",
+ briefDescription = "Activity, Service, or BroadcastReceiver marked as Singleton",
+ explanation =
+ """Activities, Services, and BroadcastReceivers are created and destroyed by
+ the Android System Server. Marking them with a Dagger scope
+ results in them being cached and reused by Dagger. Trying to reuse a
+ component like this will make for a very bad time.""",
+ category = Category.CORRECTNESS,
+ priority = 10,
+ severity = Severity.ERROR,
+ moreInfo =
+ "https://developer.android.com/guide/components/activities/process-lifecycle",
+ // Note that JAVA_FILE_SCOPE also includes Kotlin source files.
+ implementation =
+ Implementation(
+ SingletonAndroidComponentDetector::class.java,
+ Scope.JAVA_FILE_SCOPE
+ )
+ )
+
+ private val MULTIBIND_ANNOTATIONS =
+ listOf("dagger.Binds", "dagger.multibindings.IntoMap", "dagger.multibindings.ClassKey")
+
+ val MULTIPROVIDE_ANNOTATIONS =
+ listOf(
+ "dagger.Provides",
+ "dagger.multibindings.IntoMap",
+ "dagger.multibindings.ClassKey"
+ )
+ }
+}
diff --git a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt
index e93264c..cecbc47 100644
--- a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt
+++ b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt
@@ -40,6 +40,7 @@
RegisterReceiverViaContextDetector.ISSUE,
SoftwareBitmapDetector.ISSUE,
NonInjectedServiceDetector.ISSUE,
+ SingletonAndroidComponentDetector.ISSUE,
StaticSettingsProviderDetector.ISSUE,
DemotingTestWithoutBugDetector.ISSUE,
TestFunctionNameViolationDetector.ISSUE,
diff --git a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/AndroidStubs.kt b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/AndroidStubs.kt
index e1cca88..8396f3f 100644
--- a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/AndroidStubs.kt
+++ b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/AndroidStubs.kt
@@ -21,8 +21,9 @@
internal val libraryNames =
arrayOf(
- "framework.jar",
"androidx.annotation_annotation.jar",
+ "dagger2.jar",
+ "framework.jar",
"kotlinx-coroutines-core.jar",
)
diff --git a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/SingletonAndroidComponentDetectorTest.kt b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/SingletonAndroidComponentDetectorTest.kt
new file mode 100644
index 0000000..0606af8
--- /dev/null
+++ b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/SingletonAndroidComponentDetectorTest.kt
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.systemui.lint
+
+import com.android.tools.lint.checks.infrastructure.TestFile
+import com.android.tools.lint.checks.infrastructure.TestFiles
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Issue
+import org.junit.Test
+
+class SingletonAndroidComponentDetectorTest : SystemUILintDetectorTest() {
+ override fun getDetector(): Detector = SingletonAndroidComponentDetector()
+
+ override fun getIssues(): List<Issue> = listOf(SingletonAndroidComponentDetector.ISSUE)
+
+ @Test
+ fun testBindsServiceAsSingleton() {
+ lint()
+ .files(
+ TestFiles.kotlin(
+ """
+ package test.pkg
+
+ import android.app.Service
+ import com.android.systemui.dagger.SysUISingleton
+ import dagger.Binds
+ import dagger.Module
+ import dagger.multibindings.ClassKey
+ import dagger.multibindings.IntoMap
+
+ @Module
+ interface BadModule {
+ @SysUISingleton
+ @Binds
+ @IntoMap
+ @ClassKey(SingletonService::class)
+ fun bindSingletonService(service: SingletonService): Service
+ }
+ """
+ .trimIndent()
+ ),
+ *stubs
+ )
+ .issues(SingletonAndroidComponentDetector.ISSUE)
+ .run()
+ .expect(
+ """
+ src/test/pkg/BadModule.kt:12: Error: Do not bind Activities, Services, or BroadcastReceivers as Singleton. [SingletonAndroidComponent]
+ @SysUISingleton
+ ~~~~~~~~~~~~~~~
+ 1 errors, 0 warnings
+ """
+ .trimIndent()
+ )
+ }
+
+ @Test
+ fun testProvidesBroadcastReceiverAsSingleton() {
+ lint()
+ .files(
+ TestFiles.kotlin(
+ """
+ package test.pkg
+
+ import android.content.BroadcastReceiver
+ import com.android.systemui.dagger.SysUISingleton
+ import dagger.Provides
+ import dagger.Module
+ import dagger.multibindings.ClassKey
+ import dagger.multibindings.IntoMap
+
+ @Module
+ abstract class BadModule {
+ @SysUISingleton
+ @Provides
+ @IntoMap
+ @ClassKey(SingletonBroadcastReceiver::class)
+ fun providesSingletonBroadcastReceiver(br: SingletonBroadcastReceiver): BroadcastReceiver {
+ return br
+ }
+ }
+ """
+ .trimIndent()
+ ),
+ *stubs
+ )
+ .issues(SingletonAndroidComponentDetector.ISSUE)
+ .run()
+ .expect(
+ """
+ src/test/pkg/BadModule.kt:12: Error: Do not bind Activities, Services, or BroadcastReceivers as Singleton. [SingletonAndroidComponent]
+ @SysUISingleton
+ ~~~~~~~~~~~~~~~
+ 1 errors, 0 warnings
+ """
+ .trimIndent()
+ )
+ }
+ @Test
+ fun testMarksActivityAsSingleton() {
+ lint()
+ .files(
+ TestFiles.kotlin(
+ """
+ package test.pkg
+
+ import android.app.Activity
+ import com.android.systemui.dagger.SysUISingleton
+
+ @SysUISingleton
+ class BadActivity : Activity() {
+ }
+ """
+ .trimIndent()
+ ),
+ *stubs
+ )
+ .issues(SingletonAndroidComponentDetector.ISSUE)
+ .run()
+ .expect(
+ """
+ src/test/pkg/BadActivity.kt:6: Error: Do not mark Activities or Services as Singleton. [SingletonAndroidComponent]
+ @SysUISingleton
+ ~~~~~~~~~~~~~~~
+ 1 errors, 0 warnings
+ """
+ .trimIndent()
+ )
+ }
+ @Test
+ fun testMarksBroadcastReceiverAsSingleton() {
+ lint()
+ .files(
+ TestFiles.kotlin(
+ """
+ package test.pkg
+
+ import android.content.BroadcastReceiver
+ import com.android.systemui.dagger.SysUISingleton
+
+ @SysUISingleton
+ class SingletonReceveiver : BroadcastReceiver() {
+ }
+ """
+ .trimIndent()
+ ),
+ *stubs
+ )
+ .issues(SingletonAndroidComponentDetector.ISSUE)
+ .run()
+ .expectClean()
+ }
+
+ // Define stubs for Android imports. The tests don't run on Android so
+ // they don't "see" any of Android specific classes. We need to define
+ // the method parameters for proper resolution.
+ private val singletonStub: TestFile =
+ java(
+ """
+ package com.android.systemui.dagger;
+
+ public @interface SysUISingleton {
+ }
+ """
+ )
+
+ private val stubs = arrayOf(singletonStub) + androidStubs
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/shared/model/GridLayoutTypeKey.kt b/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/scene/NotificationsShadeSceneModule.kt
similarity index 61%
copy from packages/SystemUI/src/com/android/systemui/qs/panels/shared/model/GridLayoutTypeKey.kt
copy to packages/SystemUI/compose/facade/enabled/src/com/android/systemui/scene/NotificationsShadeSceneModule.kt
index 0dbaaba..9b736b8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/shared/model/GridLayoutTypeKey.kt
+++ b/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/scene/NotificationsShadeSceneModule.kt
@@ -14,15 +14,16 @@
* limitations under the License.
*/
-package com.android.systemui.qs.panels.shared.model
+package com.android.systemui.scene
-import dagger.MapKey
-import kotlin.reflect.KClass
+import com.android.systemui.notifications.ui.composable.NotificationsShadeScene
+import com.android.systemui.scene.shared.model.Scene
+import dagger.Binds
+import dagger.Module
+import dagger.multibindings.IntoSet
-/**
- * Dagger map key to associate a [GridLayoutType] with its
- * [com.android.systemui.qs.panels.ui.compose.GridLayout].
- */
-@Retention(AnnotationRetention.RUNTIME)
-@MapKey
-annotation class GridLayoutTypeKey(val value: KClass<out GridLayoutType>)
+@Module
+interface NotificationsShadeSceneModule {
+
+ @Binds @IntoSet fun notificationsShade(scene: NotificationsShadeScene): Scene
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/shared/model/GridLayoutTypeKey.kt b/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/scene/QuickSettingsShadeSceneModule.kt
similarity index 62%
copy from packages/SystemUI/src/com/android/systemui/qs/panels/shared/model/GridLayoutTypeKey.kt
copy to packages/SystemUI/compose/facade/enabled/src/com/android/systemui/scene/QuickSettingsShadeSceneModule.kt
index 0dbaaba..3d7401d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/shared/model/GridLayoutTypeKey.kt
+++ b/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/scene/QuickSettingsShadeSceneModule.kt
@@ -14,15 +14,16 @@
* limitations under the License.
*/
-package com.android.systemui.qs.panels.shared.model
+package com.android.systemui.scene
-import dagger.MapKey
-import kotlin.reflect.KClass
+import com.android.systemui.qs.ui.composable.QuickSettingsShadeScene
+import com.android.systemui.scene.shared.model.Scene
+import dagger.Binds
+import dagger.Module
+import dagger.multibindings.IntoSet
-/**
- * Dagger map key to associate a [GridLayoutType] with its
- * [com.android.systemui.qs.panels.ui.compose.GridLayout].
- */
-@Retention(AnnotationRetention.RUNTIME)
-@MapKey
-annotation class GridLayoutTypeKey(val value: KClass<out GridLayoutType>)
+@Module
+interface QuickSettingsShadeSceneModule {
+
+ @Binds @IntoSet fun quickSettingsShade(scene: QuickSettingsShadeScene): Scene
+}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt
index d59f1f5..f73b6cd 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt
@@ -28,6 +28,7 @@
import com.android.compose.animation.scene.UserActionResult
import com.android.systemui.bouncer.ui.BouncerDialogFactory
import com.android.systemui.bouncer.ui.viewmodel.BouncerViewModel
+import com.android.systemui.compose.modifiers.sysuiResTag
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.ui.composable.ComposableScene
@@ -39,6 +40,10 @@
val Background = ElementKey("BouncerBackground")
val Content = ElementKey("BouncerContent")
}
+
+ object TestTags {
+ const val Root = "bouncer_root"
+ }
}
/** The bouncer scene displays authentication challenges like PIN, password, or pattern. */
@@ -78,7 +83,9 @@
BouncerContent(
viewModel,
dialogFactory,
- Modifier.element(Bouncer.Elements.Content).fillMaxSize()
+ Modifier.sysuiResTag(Bouncer.TestTags.Root)
+ .element(Bouncer.Elements.Content)
+ .fillMaxSize()
)
}
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PasswordBouncer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PasswordBouncer.kt
index c34f2fd..2dcd0ff 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PasswordBouncer.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PasswordBouncer.kt
@@ -52,6 +52,7 @@
import com.android.compose.PlatformIconButton
import com.android.systemui.bouncer.ui.viewmodel.PasswordBouncerViewModel
import com.android.systemui.common.ui.compose.SelectedUserAwareInputConnection
+import com.android.systemui.compose.modifiers.sysuiResTag
import com.android.systemui.res.R
/** UI for the input part of a password-requiring version of the bouncer. */
@@ -105,6 +106,7 @@
),
modifier =
modifier
+ .sysuiResTag("bouncer_text_entry")
.focusRequester(focusRequester)
.onFocusChanged { viewModel.onTextFieldFocusChanged(it.isFocused) }
.drawBehind {
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PatternBouncer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PatternBouncer.kt
index 7af8408..d7e9c10 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PatternBouncer.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PatternBouncer.kt
@@ -52,6 +52,7 @@
import com.android.internal.R
import com.android.systemui.bouncer.ui.viewmodel.PatternBouncerViewModel
import com.android.systemui.bouncer.ui.viewmodel.PatternDotViewModel
+import com.android.systemui.compose.modifiers.sysuiResTag
import kotlin.math.min
import kotlin.math.pow
import kotlin.math.sqrt
@@ -234,6 +235,7 @@
Canvas(
modifier
+ .sysuiResTag("bouncer_pattern_root")
// Because the width also includes spacing to the left and right of the leftmost and
// rightmost dots in the grid and because UX mocks specify the width without that
// spacing, the actual width needs to be defined slightly bigger than the UX mock width.
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/common/ui/compose/windowinsets/DisplayCutout.kt b/packages/SystemUI/compose/features/src/com/android/systemui/common/ui/compose/windowinsets/DisplayCutout.kt
index 8dda067..3eb1b14 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/common/ui/compose/windowinsets/DisplayCutout.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/common/ui/compose/windowinsets/DisplayCutout.kt
@@ -16,6 +16,7 @@
package com.android.systemui.common.ui.compose.windowinsets
+import android.view.DisplayCutout as ViewDisplayCutout
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import kotlin.math.abs
@@ -27,6 +28,11 @@
val right: Dp = 0.dp,
val bottom: Dp = 0.dp,
val location: CutoutLocation = CutoutLocation.NONE,
+ /**
+ * The original `DisplayCutout` for the `View` world; only use this when feeding it back to a
+ * `View`.
+ */
+ val viewDisplayCutoutKeyguardStatusBarView: ViewDisplayCutout? = null,
) {
fun width() = abs(right.value - left.value).dp
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
index dff9b3b..79b57ca7 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
@@ -24,7 +24,11 @@
import android.view.View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
import android.widget.FrameLayout
import androidx.compose.animation.AnimatedVisibility
+import androidx.compose.animation.AnimatedVisibilityScope
+import androidx.compose.animation.ExperimentalAnimationApi
+import androidx.compose.animation.core.LinearEasing
import androidx.compose.animation.core.animateFloatAsState
+import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.BorderStroke
@@ -83,10 +87,13 @@
import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.alpha
+import androidx.compose.ui.draw.scale
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.ColorMatrix
+import androidx.compose.ui.graphics.TransformOrigin
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.input.key.onPreviewKeyEvent
import androidx.compose.ui.input.pointer.motionEventSpy
@@ -289,23 +296,21 @@
removeEnabled = removeButtonEnabled
)
}
+ if (currentPopup == PopupType.CtaTile) {
+ PopupOnDismissCtaTile(viewModel::onHidePopup)
+ }
- if (currentPopup != null) {
- when (currentPopup) {
- PopupType.CtaTile -> {
- PopupOnDismissCtaTile(viewModel::onHidePopup)
- }
- PopupType.CustomizeWidgetButton -> {
- ButtonToEditWidgets(
- onClick = {
- viewModel.onHidePopup()
- viewModel.onOpenWidgetEditor(selectedKey.value)
- },
- onHide = { viewModel.onHidePopup() }
- )
- }
- null -> {}
- }
+ AnimatedVisibility(
+ visible = currentPopup == PopupType.CustomizeWidgetButton,
+ modifier = Modifier.fillMaxSize()
+ ) {
+ ButtonToEditWidgets(
+ onClick = {
+ viewModel.onHidePopup()
+ viewModel.onOpenWidgetEditor(selectedKey.value)
+ },
+ onHide = { viewModel.onHidePopup() }
+ )
}
if (viewModel is CommunalViewModel && dialogFactory != null) {
@@ -464,6 +469,8 @@
size = size,
selected = selected && !isDragging,
widgetConfigurator = widgetConfigurator,
+ index = index,
+ contentListState = contentListState
)
}
} else {
@@ -473,6 +480,8 @@
viewModel = viewModel,
size = size,
selected = false,
+ index = index,
+ contentListState = contentListState
)
}
}
@@ -654,30 +663,67 @@
}
}
+@OptIn(ExperimentalAnimationApi::class)
@Composable
-private fun ButtonToEditWidgets(
+private fun AnimatedVisibilityScope.ButtonToEditWidgets(
onClick: () -> Unit,
onHide: () -> Unit,
) {
- Popup(alignment = Alignment.TopCenter, offset = IntOffset(0, 40), onDismissRequest = onHide) {
+ Popup(
+ alignment = Alignment.TopCenter,
+ offset = IntOffset(0, 40),
+ onDismissRequest = onHide,
+ ) {
val colors = LocalAndroidColorScheme.current
Button(
modifier =
- Modifier.height(56.dp).background(colors.secondary, RoundedCornerShape(50.dp)),
+ Modifier.height(56.dp)
+ .graphicsLayer { transformOrigin = TransformOrigin(0f, 0f) }
+ .animateEnterExit(
+ enter =
+ fadeIn(
+ initialAlpha = 0f,
+ animationSpec = tween(durationMillis = 500, easing = LinearEasing)
+ ),
+ exit =
+ fadeOut(
+ animationSpec = tween(durationMillis = 500, easing = LinearEasing)
+ )
+ )
+ .background(colors.secondary, RoundedCornerShape(50.dp)),
onClick = onClick,
) {
- Icon(
- imageVector = Icons.Outlined.Widgets,
- contentDescription = stringResource(R.string.button_to_configure_widgets_text),
- tint = colors.onSecondary,
- modifier = Modifier.size(20.dp)
- )
- Spacer(modifier = Modifier.size(8.dp))
- Text(
- text = stringResource(R.string.button_to_configure_widgets_text),
- style = MaterialTheme.typography.titleSmall,
- color = colors.onSecondary,
- )
+ Row(
+ modifier =
+ Modifier.animateEnterExit(
+ enter =
+ fadeIn(
+ animationSpec =
+ tween(
+ durationMillis = 167,
+ delayMillis = 500,
+ easing = LinearEasing
+ )
+ ),
+ exit =
+ fadeOut(
+ animationSpec = tween(durationMillis = 167, easing = LinearEasing)
+ )
+ )
+ ) {
+ Icon(
+ imageVector = Icons.Outlined.Widgets,
+ contentDescription = stringResource(R.string.button_to_configure_widgets_text),
+ tint = colors.onSecondary,
+ modifier = Modifier.size(20.dp)
+ )
+ Spacer(modifier = Modifier.size(8.dp))
+ Text(
+ text = stringResource(R.string.button_to_configure_widgets_text),
+ style = MaterialTheme.typography.titleSmall,
+ color = colors.onSecondary
+ )
+ }
}
}
}
@@ -740,10 +786,21 @@
selected: Boolean,
modifier: Modifier = Modifier,
widgetConfigurator: WidgetConfigurator? = null,
+ index: Int,
+ contentListState: ContentListState,
) {
when (model) {
is CommunalContentModel.WidgetContent.Widget ->
- WidgetContent(viewModel, model, size, selected, widgetConfigurator, modifier)
+ WidgetContent(
+ viewModel,
+ model,
+ size,
+ selected,
+ widgetConfigurator,
+ modifier,
+ index,
+ contentListState
+ )
is CommunalContentModel.WidgetPlaceholder -> HighlightedItem(modifier)
is CommunalContentModel.WidgetContent.DisabledWidget ->
DisabledWidgetPlaceholder(model, viewModel, modifier)
@@ -841,6 +898,8 @@
selected: Boolean,
widgetConfigurator: WidgetConfigurator?,
modifier: Modifier = Modifier,
+ index: Int,
+ contentListState: ContentListState,
) {
val context = LocalContext.current
val isFocusable by viewModel.isFocusable.collectAsState(initial = false)
@@ -849,6 +908,11 @@
model.providerInfo.loadLabel(context.packageManager).toString().trim()
}
val clickActionLabel = stringResource(R.string.accessibility_action_label_select_widget)
+ val removeWidgetActionLabel = stringResource(R.string.accessibility_action_label_remove_widget)
+ val placeWidgetActionLabel = stringResource(R.string.accessibility_action_label_place_widget)
+ val selectedKey by viewModel.selectedKey.collectAsState()
+ val selectedIndex =
+ selectedKey?.let { key -> contentListState.list.indexOfFirst { it.key == key } }
Box(
modifier =
modifier
@@ -865,6 +929,36 @@
Modifier.semantics {
contentDescription = accessibilityLabel
onClick(label = clickActionLabel, action = null)
+ val deleteAction =
+ CustomAccessibilityAction(removeWidgetActionLabel) {
+ contentListState.onRemove(index)
+ contentListState.onSaveList()
+ true
+ }
+ val selectWidgetAction =
+ CustomAccessibilityAction(clickActionLabel) {
+ val currentWidgetKey =
+ index?.let {
+ keyAtIndexIfEditable(contentListState.list, index)
+ }
+ viewModel.setSelectedKey(currentWidgetKey)
+ true
+ }
+
+ val actions = mutableListOf(deleteAction, selectWidgetAction)
+
+ if (selectedIndex != null && selectedIndex != index) {
+ actions.add(
+ CustomAccessibilityAction(placeWidgetActionLabel) {
+ contentListState.onMove(selectedIndex!!, index)
+ contentListState.onSaveList()
+ viewModel.setSelectedKey(null)
+ true
+ }
+ )
+ }
+
+ customActions = actions
}
}
) {
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/StatusBarSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/StatusBarSection.kt
index ddc12ff..d996d25 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/StatusBarSection.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/StatusBarSection.kt
@@ -23,6 +23,7 @@
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
@@ -31,6 +32,7 @@
import com.android.compose.animation.scene.SceneScope
import com.android.compose.modifiers.height
import com.android.keyguard.dagger.KeyguardStatusBarViewComponent
+import com.android.systemui.common.ui.compose.windowinsets.LocalDisplayCutout
import com.android.systemui.res.R
import com.android.systemui.shade.NotificationPanelView
import com.android.systemui.shade.ShadeViewStateProvider
@@ -48,6 +50,31 @@
@Composable
fun SceneScope.StatusBar(modifier: Modifier = Modifier) {
val context = LocalContext.current
+ val viewDisplayCutout = LocalDisplayCutout.current.viewDisplayCutoutKeyguardStatusBarView
+ @SuppressLint("InflateParams")
+ val view =
+ remember(context) {
+ LayoutInflater.from(context)
+ .inflate(
+ R.layout.keyguard_status_bar,
+ null,
+ false,
+ ) as KeyguardStatusBarView
+ }
+ val viewController =
+ remember(view) {
+ val provider =
+ object : ShadeViewStateProvider {
+ override val lockscreenShadeDragProgress: Float = 0f
+ override val panelViewExpandedHeight: Float = 0f
+
+ override fun shouldHeadsUpBeVisible(): Boolean {
+ return false
+ }
+ }
+
+ componentFactory.build(view, provider).keyguardStatusBarViewController
+ }
MovableElement(
key = StatusBarElementKey,
@@ -60,34 +87,14 @@
(it.parent as ViewGroup).removeView(it)
}
- val provider =
- object : ShadeViewStateProvider {
- override val lockscreenShadeDragProgress: Float = 0f
- override val panelViewExpandedHeight: Float = 0f
-
- override fun shouldHeadsUpBeVisible(): Boolean {
- return false
- }
- }
-
- @SuppressLint("InflateParams")
- val view =
- LayoutInflater.from(context)
- .inflate(
- R.layout.keyguard_status_bar,
- null,
- false,
- ) as KeyguardStatusBarView
- componentFactory
- .build(view, provider)
- .keyguardStatusBarViewController
- .init()
+ viewController.init()
view
},
modifier =
Modifier.fillMaxWidth().padding(horizontal = 16.dp).height {
Utils.getStatusBarHeaderHeightKeyguard(context)
},
+ update = { viewController.setDisplayCutout(viewDisplayCutout) }
)
}
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/TopAreaSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/TopAreaSection.kt
index 722032c..63c70c9 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/TopAreaSection.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/TopAreaSection.kt
@@ -36,6 +36,7 @@
import com.android.compose.animation.scene.SceneScope
import com.android.compose.animation.scene.SceneTransitionLayout
import com.android.compose.modifiers.thenIf
+import com.android.systemui.compose.modifiers.sysuiResTag
import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor
import com.android.systemui.keyguard.ui.composable.blueprint.ClockScenes.largeClockScene
import com.android.systemui.keyguard.ui.composable.blueprint.ClockScenes.smallClockScene
@@ -79,7 +80,7 @@
}
SceneTransitionLayout(
- modifier = modifier,
+ modifier = modifier.sysuiResTag("keyguard_clock_container"),
currentScene = currentScene,
onChangeScene = {},
transitions = ClockTransition.defaultClockTransitions,
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationScrimNestedScrollConnection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationScrimNestedScrollConnection.kt
index 2ba78cf..fdf82ca 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationScrimNestedScrollConnection.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationScrimNestedScrollConnection.kt
@@ -30,11 +30,15 @@
*/
fun NotificationScrimNestedScrollConnection(
scrimOffset: () -> Float,
- onScrimOffsetChanged: (Float) -> Unit,
+ snapScrimOffset: (Float) -> Unit,
+ animateScrimOffset: (Float) -> Unit,
minScrimOffset: () -> Float,
maxScrimOffset: Float,
contentHeight: () -> Float,
minVisibleScrimHeight: () -> Float,
+ isCurrentGestureOverscroll: () -> Boolean,
+ onStart: (Float) -> Unit = {},
+ onStop: (Float) -> Unit = {},
): PriorityNestedScrollConnection {
return PriorityNestedScrollConnection(
orientation = Orientation.Vertical,
@@ -49,7 +53,7 @@
// scrolling down and content is done scrolling to top. After that, the scrim
// needs to collapse; collapse the scrim until it is at the maxScrimOffset.
canStartPostScroll = { offsetAvailable, _ ->
- offsetAvailable > 0 && scrimOffset() < maxScrimOffset
+ offsetAvailable > 0 && (scrimOffset() < maxScrimOffset || isCurrentGestureOverscroll())
},
canStartPostFling = { false },
canContinueScroll = {
@@ -57,7 +61,7 @@
minScrimOffset() < currentHeight && currentHeight < maxScrimOffset
},
canScrollOnFling = true,
- onStart = { /* do nothing */},
+ onStart = { offsetAvailable -> onStart(offsetAvailable) },
onScroll = { offsetAvailable ->
val currentHeight = scrimOffset()
val amountConsumed =
@@ -68,10 +72,16 @@
val amountLeft = minScrimOffset() - currentHeight
offsetAvailable.coerceAtLeast(amountLeft)
}
- onScrimOffsetChanged(currentHeight + amountConsumed)
+ snapScrimOffset(currentHeight + amountConsumed)
amountConsumed
},
// Don't consume the velocity on pre/post fling
- onStop = { 0f },
+ onStop = { velocityAvailable ->
+ onStop(velocityAvailable)
+ if (scrimOffset() < minScrimOffset()) {
+ animateScrimOffset(minScrimOffset())
+ }
+ 0f
+ },
)
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt
index 985d3a1..3ce0feb 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt
@@ -18,6 +18,8 @@
package com.android.systemui.notifications.ui.composable
import android.util.Log
+import androidx.compose.animation.core.Animatable
+import androidx.compose.foundation.ScrollState
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.scrollBy
import androidx.compose.foundation.layout.Box
@@ -29,7 +31,6 @@
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.systemBars
-import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.MaterialTheme
@@ -39,8 +40,7 @@
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
+import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@@ -65,11 +65,12 @@
import com.android.compose.animation.scene.ElementKey
import com.android.compose.animation.scene.NestedScrollBehavior
import com.android.compose.animation.scene.SceneScope
-import com.android.compose.animation.scene.SceneTransitionLayoutState
import com.android.compose.modifiers.height
import com.android.systemui.common.ui.compose.windowinsets.LocalRawScreenHeight
import com.android.systemui.common.ui.compose.windowinsets.LocalScreenCornerRadius
import com.android.systemui.res.R
+import com.android.systemui.scene.session.ui.composable.SaveableSession
+import com.android.systemui.scene.session.ui.composable.rememberSession
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.shade.ui.composable.ShadeHeader
import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimBounds
@@ -78,6 +79,7 @@
import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationTransitionThresholds.EXPANSION_FOR_MAX_SCRIM_ALPHA
import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationsPlaceholderViewModel
import kotlin.math.roundToInt
+import kotlinx.coroutines.launch
object Notifications {
object Elements {
@@ -155,15 +157,22 @@
*/
@Composable
fun SceneScope.NotificationScrollingStack(
+ shadeSession: SaveableSession,
viewModel: NotificationsPlaceholderViewModel,
maxScrimTop: () -> Float,
+ shouldPunchHoleBehindScrim: Boolean,
modifier: Modifier = Modifier,
) {
+ val coroutineScope = rememberCoroutineScope()
val density = LocalDensity.current
val screenCornerRadius = LocalScreenCornerRadius.current
val scrimCornerRadius = dimensionResource(R.dimen.notification_scrim_corner_radius)
- val scrollState = rememberScrollState()
+ val scrollState =
+ shadeSession.rememberSaveableSession(saver = ScrollState.Saver, key = null) {
+ ScrollState(initial = 0)
+ }
val syntheticScroll = viewModel.syntheticScroll.collectAsState(0f)
+ val isCurrentGestureOverscroll = viewModel.isCurrentGestureOverscroll.collectAsState(false)
val expansionFraction by viewModel.expandFraction.collectAsState(0f)
val navBarHeight =
@@ -180,7 +189,7 @@
// When fully expanded (scrimOffset = minScrimOffset), its top bound is at minScrimStartY,
// which is equal to the height of the Shade Header. Thus, when the scrim is fully expanded, the
// entire height of the scrim is visible on screen.
- val scrimOffset = remember { mutableStateOf(0f) }
+ val scrimOffset = shadeSession.rememberSession { Animatable(0f) }
// set the bounds to null when the scrim disappears
DisposableEffect(Unit) { onDispose { viewModel.onScrimBoundsChanged(null) } }
@@ -204,7 +213,7 @@
// expanded, reset scrim offset.
LaunchedEffect(stackHeight, scrimOffset) {
snapshotFlow { stackHeight.value < minVisibleScrimHeight() && scrimOffset.value < 0f }
- .collect { shouldCollapse -> if (shouldCollapse) scrimOffset.value = 0f }
+ .collect { shouldCollapse -> if (shouldCollapse) scrimOffset.snapTo(0f) }
}
// if we receive scroll delta from NSSL, offset the scrim and placeholder accordingly.
@@ -214,7 +223,7 @@
val minOffset = minScrimOffset()
if (scrimOffset.value > minOffset) {
val remainingDelta = (minOffset - (scrimOffset.value - delta)).coerceAtLeast(0f)
- scrimOffset.value = (scrimOffset.value - delta).coerceAtLeast(minOffset)
+ scrimOffset.snapTo((scrimOffset.value - delta).coerceAtLeast(minOffset))
if (remainingDelta > 0f) {
scrollState.scrollBy(remainingDelta)
}
@@ -233,7 +242,8 @@
// in step with the transition so that it is 0 when it completes.
if (
scrimOffset.value < 0 &&
- layoutState.isTransitioning(from = Scenes.Shade, to = Scenes.Gone)
+ layoutState.isTransitioning(from = Scenes.Shade, to = Scenes.Gone) ||
+ layoutState.isTransitioning(from = Scenes.Shade, to = Scenes.Lockscreen)
) {
IntOffset(x = 0, y = (scrimOffset.value * expansionFraction).roundToInt())
} else {
@@ -246,7 +256,7 @@
scrimCornerRadius,
screenCornerRadius,
{ expansionFraction },
- layoutState.isNotificationScrimTransitioning(),
+ shouldPunchHoleBehindScrim,
)
.let { scrimRounding.value.toRoundedCornerShape(it) }
clip = true
@@ -270,18 +280,20 @@
) {
// Creates a cutout in the background scrim in the shape of the notifications scrim.
// Only visible when notif scrim alpha < 1, during shade expansion.
- Spacer(
- modifier =
- Modifier.fillMaxSize().drawBehind {
- drawRect(Color.Black, blendMode = BlendMode.DstOut)
- }
- )
+ if (shouldPunchHoleBehindScrim) {
+ Spacer(
+ modifier =
+ Modifier.fillMaxSize().drawBehind {
+ drawRect(Color.Black, blendMode = BlendMode.DstOut)
+ }
+ )
+ }
Box(
modifier =
Modifier.fillMaxSize()
.graphicsLayer {
alpha =
- if (layoutState.isNotificationScrimTransitioning()) {
+ if (shouldPunchHoleBehindScrim) {
(expansionFraction / EXPANSION_FOR_MAX_SCRIM_ALPHA).coerceAtMost(1f)
} else 1f
}
@@ -293,20 +305,30 @@
modifier =
Modifier.verticalNestedScrollToScene(
topBehavior = NestedScrollBehavior.EdgeWithPreview,
+ isExternalOverscrollGesture = { isCurrentGestureOverscroll.value }
)
.nestedScroll(
- remember(
+ shadeSession.rememberSession(
scrimOffset,
maxScrimTop,
minScrimTop,
+ isCurrentGestureOverscroll,
) {
NotificationScrimNestedScrollConnection(
scrimOffset = { scrimOffset.value },
- onScrimOffsetChanged = { scrimOffset.value = it },
+ snapScrimOffset = { value ->
+ coroutineScope.launch { scrimOffset.snapTo(value) }
+ },
+ animateScrimOffset = { value ->
+ coroutineScope.launch { scrimOffset.animateTo(value) }
+ },
minScrimOffset = minScrimOffset,
maxScrimOffset = 0f,
contentHeight = { stackHeight.value },
minVisibleScrimHeight = minVisibleScrimHeight,
+ isCurrentGestureOverscroll = {
+ isCurrentGestureOverscroll.value
+ },
)
}
)
@@ -429,13 +451,6 @@
)
}
-private fun SceneTransitionLayoutState.isNotificationScrimTransitioning(): Boolean {
- return isTransitioningBetween(Scenes.Gone, Scenes.Shade) ||
- isTransitioningBetween(Scenes.Lockscreen, Scenes.Shade) ||
- isTransitioningBetween(Scenes.Gone, Scenes.QuickSettings) ||
- isTransitioningBetween(Scenes.Lockscreen, Scenes.QuickSettings)
-}
-
private const val TAG = "FlexiNotifs"
private val DEBUG_STACK_COLOR = Color(1f, 0f, 0f, 0.2f)
private val DEBUG_HUN_COLOR = Color(0f, 0f, 1f, 0.2f)
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeScene.kt
new file mode 100644
index 0000000..1c675e3
--- /dev/null
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeScene.kt
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.notifications.ui.composable
+
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.dp
+import com.android.compose.animation.scene.SceneScope
+import com.android.compose.animation.scene.UserAction
+import com.android.compose.animation.scene.UserActionResult
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.notifications.ui.viewmodel.NotificationsShadeSceneViewModel
+import com.android.systemui.scene.shared.model.Scenes
+import com.android.systemui.scene.ui.composable.ComposableScene
+import com.android.systemui.shade.ui.composable.OverlayShade
+import com.android.systemui.shade.ui.viewmodel.OverlayShadeViewModel
+import javax.inject.Inject
+import kotlinx.coroutines.flow.StateFlow
+
+@SysUISingleton
+class NotificationsShadeScene
+@Inject
+constructor(
+ viewModel: NotificationsShadeSceneViewModel,
+ private val overlayShadeViewModel: OverlayShadeViewModel,
+) : ComposableScene {
+
+ override val key = Scenes.NotificationsShade
+
+ override val destinationScenes: StateFlow<Map<UserAction, UserActionResult>> =
+ viewModel.destinationScenes
+
+ @Composable
+ override fun SceneScope.Content(
+ modifier: Modifier,
+ ) {
+ OverlayShade(
+ viewModel = overlayShadeViewModel,
+ modifier = modifier,
+ horizontalArrangement = Arrangement.Start,
+ ) {
+ Text(
+ text = "Notifications list",
+ modifier = Modifier.padding(NotificationsShade.Dimensions.Padding)
+ )
+ }
+ }
+}
+
+object NotificationsShade {
+ object Dimensions {
+ val Padding = 16.dp
+ }
+}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeSessionModule.kt b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeSessionModule.kt
new file mode 100644
index 0000000..076c917
--- /dev/null
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeSessionModule.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.notifications.ui.composable
+
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.saveable.Saver
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.scene.session.shared.SessionStorage
+import com.android.systemui.scene.session.ui.composable.SaveableSession
+import com.android.systemui.scene.session.ui.composable.Session
+import dagger.Module
+import dagger.Provides
+
+@Module
+object NotificationsShadeSessionModule {
+ @Provides @SysUISingleton fun provideShadeSessionStorage(): SessionStorage = SessionStorage()
+
+ @Provides
+ fun provideShadeSession(storage: SessionStorage): SaveableSession =
+ object : SaveableSession, Session by Session(storage) {
+ @Composable
+ override fun <T : Any> rememberSaveableSession(
+ vararg inputs: Any?,
+ saver: Saver<T, out Any>,
+ key: String?,
+ init: () -> T
+ ): T = rememberSession(key, inputs = inputs, init = init)
+ }
+}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/FooterActions.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/FooterActions.kt
index eedff89..5f84dd4 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/FooterActions.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/FooterActions.kt
@@ -17,6 +17,11 @@
package com.android.systemui.qs.footer.ui.compose
import androidx.compose.animation.AnimatedVisibility
+import androidx.compose.animation.core.tween
+import androidx.compose.animation.expandVertically
+import androidx.compose.animation.fadeIn
+import androidx.compose.animation.fadeOut
+import androidx.compose.animation.shrinkVertically
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.LocalIndication
@@ -87,10 +92,24 @@
fun SceneScope.FooterActionsWithAnimatedVisibility(
viewModel: FooterActionsViewModel,
isCustomizing: Boolean,
+ customizingAnimationDuration: Int,
lifecycleOwner: LifecycleOwner,
modifier: Modifier = Modifier,
) {
- AnimatedVisibility(visible = !isCustomizing, modifier = modifier.fillMaxWidth()) {
+ AnimatedVisibility(
+ visible = !isCustomizing,
+ enter =
+ expandVertically(
+ animationSpec = tween(customizingAnimationDuration),
+ initialHeight = { 0 },
+ ) + fadeIn(tween(customizingAnimationDuration)),
+ exit =
+ shrinkVertically(
+ animationSpec = tween(customizingAnimationDuration),
+ targetHeight = { 0 },
+ ) + fadeOut(tween(customizingAnimationDuration)),
+ modifier = modifier.fillMaxWidth()
+ ) {
QuickSettingsTheme {
// This view has its own horizontal padding
// TODO(b/321716470) This should use a lifecycle tied to the scene.
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettings.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettings.kt
index a87a8df..46be6b8 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettings.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettings.kt
@@ -162,7 +162,8 @@
modifier: Modifier = Modifier,
) {
val qsView by qsSceneAdapter.qsView.collectAsState(null)
- val isCustomizing by qsSceneAdapter.isCustomizing.collectAsState()
+ val isCustomizing by
+ qsSceneAdapter.isCustomizerShowing.collectAsState(qsSceneAdapter.isCustomizerShowing.value)
QuickSettingsTheme {
val context = LocalContext.current
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt
index 62619f5..ec9136d 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt
@@ -19,12 +19,15 @@
import android.view.ViewGroup
import androidx.activity.compose.BackHandler
import androidx.compose.animation.AnimatedVisibility
+import androidx.compose.animation.core.animateDpAsState
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.tween
import androidx.compose.animation.expandVertically
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.shrinkVertically
+import androidx.compose.animation.slideInVertically
+import androidx.compose.animation.slideOutVertically
import androidx.compose.foundation.background
import androidx.compose.foundation.clipScrollableContainer
import androidx.compose.foundation.gestures.Orientation
@@ -45,6 +48,7 @@
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
@@ -61,6 +65,7 @@
import com.android.compose.animation.scene.SceneScope
import com.android.compose.animation.scene.TransitionState
import com.android.compose.animation.scene.animateSceneFloatAsState
+import com.android.compose.modifiers.thenIf
import com.android.compose.windowsizeclass.LocalWindowSizeClass
import com.android.systemui.battery.BatteryMeterViewController
import com.android.systemui.common.ui.compose.windowinsets.LocalRawScreenHeight
@@ -75,6 +80,7 @@
import com.android.systemui.qs.footer.ui.compose.FooterActionsWithAnimatedVisibility
import com.android.systemui.qs.ui.viewmodel.QuickSettingsSceneViewModel
import com.android.systemui.res.R
+import com.android.systemui.scene.session.ui.composable.SaveableSession
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.ui.composable.ComposableScene
import com.android.systemui.shade.ui.composable.CollapsedShadeHeader
@@ -98,6 +104,7 @@
@Inject
constructor(
@Application private val applicationScope: CoroutineScope,
+ private val shadeSession: SaveableSession,
private val viewModel: QuickSettingsSceneViewModel,
private val notificationsPlaceholderViewModel: NotificationsPlaceholderViewModel,
private val tintedIconManagerFactory: TintedIconManager.Factory,
@@ -128,6 +135,7 @@
mediaCarouselController = mediaCarouselController,
mediaHost = mediaHost,
modifier = modifier,
+ shadeSession = shadeSession,
)
}
}
@@ -142,6 +150,7 @@
mediaCarouselController: MediaCarouselController,
mediaHost: MediaHost,
modifier: Modifier = Modifier,
+ shadeSession: SaveableSession,
) {
val brightnessMirrorShowing by viewModel.brightnessMirrorViewModel.isShowing.collectAsState()
val contentAlpha by
@@ -150,22 +159,35 @@
label = "alphaAnimationBrightnessMirrorContentHiding",
)
+ viewModel.notifications.setAlphaForBrightnessMirror(contentAlpha)
+ DisposableEffect(Unit) { onDispose { viewModel.notifications.setAlphaForBrightnessMirror(1f) } }
+
BrightnessMirror(
viewModel = viewModel.brightnessMirrorViewModel,
qsSceneAdapter = viewModel.qsSceneAdapter
)
+ val shouldPunchHoleBehindScrim =
+ layoutState.isTransitioningBetween(Scenes.Gone, Scenes.QuickSettings) ||
+ layoutState.isTransitioningBetween(Scenes.Lockscreen, Scenes.QuickSettings)
+
// TODO(b/280887232): implement the real UI.
Box(
modifier =
- modifier.fillMaxSize().graphicsLayer {
- // Render the scene to an offscreen buffer so that BlendMode.DstOut only clears this
- // scene (and not the one under it) during a scene transition.
- compositingStrategy = CompositingStrategy.Offscreen
- alpha = contentAlpha
- }
+ modifier
+ .fillMaxSize()
+ .graphicsLayer { alpha = contentAlpha }
+ .thenIf(shouldPunchHoleBehindScrim) {
+ // Render the scene to an offscreen buffer so that BlendMode.DstOut only clears
+ // this
+ // scene (and not the one under it) during a scene transition.
+ Modifier.graphicsLayer(compositingStrategy = CompositingStrategy.Offscreen)
+ }
) {
val isCustomizing by viewModel.qsSceneAdapter.isCustomizing.collectAsState()
+ val isCustomizerShowing by viewModel.qsSceneAdapter.isCustomizerShowing.collectAsState()
+ val customizingAnimationDuration by
+ viewModel.qsSceneAdapter.customizerAnimationDuration.collectAsState()
val screenHeight = LocalRawScreenHeight.current
BackHandler(
@@ -205,6 +227,18 @@
val navBarBottomHeight =
WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding()
val density = LocalDensity.current
+ val bottomPadding by
+ animateDpAsState(
+ targetValue = if (isCustomizing) 0.dp else navBarBottomHeight,
+ animationSpec = tween(customizingAnimationDuration),
+ label = "animateQSSceneBottomPaddingAsState"
+ )
+ val topPadding by
+ animateDpAsState(
+ targetValue = if (isCustomizing) ShadeHeader.Dimensions.CollapsedHeight else 0.dp,
+ animationSpec = tween(customizingAnimationDuration),
+ label = "animateQSSceneTopPaddingAsState"
+ )
LaunchedEffect(navBarBottomHeight, density) {
with(density) {
@@ -224,17 +258,14 @@
horizontalAlignment = Alignment.CenterHorizontally,
modifier =
Modifier.fillMaxSize()
- .then(
- if (isCustomizing) {
- Modifier.padding(top = 48.dp)
- } else {
- Modifier.padding(bottom = navBarBottomHeight)
- }
+ .padding(
+ top = topPadding.coerceAtLeast(0.dp),
+ bottom = bottomPadding.coerceAtLeast(0.dp)
)
) {
Box(modifier = Modifier.fillMaxSize().weight(1f)) {
val shadeHeaderAndQuickSettingsModifier =
- if (isCustomizing) {
+ if (isCustomizerShowing) {
Modifier.fillMaxHeight().align(Alignment.TopCenter)
} else {
Modifier.verticalNestedScrollToScene()
@@ -257,15 +288,22 @@
visible = !isCustomizing,
enter =
expandVertically(
- animationSpec = tween(100),
- initialHeight = { collapsedHeaderHeight },
- ) + fadeIn(tween(100)),
+ animationSpec = tween(customizingAnimationDuration),
+ expandFrom = Alignment.Top,
+ ) +
+ slideInVertically(
+ animationSpec = tween(customizingAnimationDuration),
+ ) +
+ fadeIn(tween(customizingAnimationDuration)),
exit =
shrinkVertically(
- animationSpec = tween(100),
- targetHeight = { collapsedHeaderHeight },
+ animationSpec = tween(customizingAnimationDuration),
shrinkTowards = Alignment.Top,
- ) + fadeOut(tween(100)),
+ ) +
+ slideOutVertically(
+ animationSpec = tween(customizingAnimationDuration),
+ ) +
+ fadeOut(tween(customizingAnimationDuration)),
) {
ExpandedShadeHeader(
viewModel = viewModel.shadeHeaderViewModel,
@@ -291,7 +329,7 @@
viewModel.qsSceneAdapter,
{ viewModel.qsSceneAdapter.qsHeight },
isSplitShade = false,
- modifier = Modifier.sysuiResTag("expanded_qs_scroll_view"),
+ modifier = Modifier.sysuiResTag("expanded_qs_scroll_view")
)
MediaCarousel(
@@ -306,13 +344,16 @@
FooterActionsWithAnimatedVisibility(
viewModel = footerActionsViewModel,
isCustomizing = isCustomizing,
+ customizingAnimationDuration = customizingAnimationDuration,
lifecycleOwner = lifecycleOwner,
modifier = Modifier.align(Alignment.CenterHorizontally),
)
}
NotificationScrollingStack(
viewModel = notificationsPlaceholderViewModel,
+ shadeSession = shadeSession,
maxScrimTop = { screenHeight },
+ shouldPunchHoleBehindScrim = shouldPunchHoleBehindScrim,
modifier =
Modifier.fillMaxWidth().offset { IntOffset(x = 0, y = screenHeight.roundToInt()) },
)
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeScene.kt
new file mode 100644
index 0000000..636c6c3
--- /dev/null
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeScene.kt
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.ui.composable
+
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.dp
+import com.android.compose.animation.scene.SceneScope
+import com.android.compose.animation.scene.UserAction
+import com.android.compose.animation.scene.UserActionResult
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.qs.ui.viewmodel.QuickSettingsShadeSceneViewModel
+import com.android.systemui.scene.shared.model.Scenes
+import com.android.systemui.scene.ui.composable.ComposableScene
+import com.android.systemui.shade.ui.composable.OverlayShade
+import com.android.systemui.shade.ui.viewmodel.OverlayShadeViewModel
+import javax.inject.Inject
+import kotlinx.coroutines.flow.StateFlow
+
+@SysUISingleton
+class QuickSettingsShadeScene
+@Inject
+constructor(
+ viewModel: QuickSettingsShadeSceneViewModel,
+ private val overlayShadeViewModel: OverlayShadeViewModel,
+) : ComposableScene {
+
+ override val key = Scenes.QuickSettingsShade
+
+ override val destinationScenes: StateFlow<Map<UserAction, UserActionResult>> =
+ viewModel.destinationScenes
+
+ @Composable
+ override fun SceneScope.Content(
+ modifier: Modifier,
+ ) {
+ OverlayShade(
+ viewModel = overlayShadeViewModel,
+ modifier = modifier,
+ horizontalArrangement = Arrangement.End,
+ ) {
+ Text(
+ text = "Quick settings grid",
+ modifier = Modifier.padding(QuickSettingsShade.Dimensions.Padding)
+ )
+ }
+ }
+}
+
+object QuickSettingsShade {
+ object Dimensions {
+ val Padding = 16.dp
+ }
+}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/session/shared/SessionStorage.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/session/shared/SessionStorage.kt
new file mode 100644
index 0000000..dc58919
--- /dev/null
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/session/shared/SessionStorage.kt
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.scene.session.shared
+
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.setValue
+
+/** Data store for [Session][com.android.systemui.scene.session.ui.composable.Session]. */
+class SessionStorage {
+ private var _storage by mutableStateOf(hashMapOf<String, StorageEntry>())
+
+ /**
+ * Data store containing all state retained for invocations of
+ * [rememberSession][com.android.systemui.scene.session.ui.composable.Session.rememberSession]
+ */
+ val storage: MutableMap<String, StorageEntry>
+ get() = _storage
+
+ /**
+ * Storage for an individual invocation of
+ * [rememberSession][com.android.systemui.scene.session.ui.composable.Session.rememberSession]
+ */
+ class StorageEntry(val keys: Array<out Any?>, var stored: Any?)
+
+ /** Clears the data store; any downstream usage within `@Composable`s will be recomposed. */
+ fun clear() {
+ _storage = hashMapOf()
+ }
+}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/session/ui/composable/Session.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/session/ui/composable/Session.kt
new file mode 100644
index 0000000..924aa54
--- /dev/null
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/session/ui/composable/Session.kt
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.scene.session.ui.composable
+
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.SideEffect
+import androidx.compose.runtime.currentCompositeKeyHash
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.saveable.Saver
+import androidx.compose.runtime.saveable.SaverScope
+import androidx.compose.runtime.saveable.mapSaver
+import androidx.compose.runtime.saveable.rememberSaveable
+import androidx.compose.runtime.setValue
+import com.android.systemui.scene.session.shared.SessionStorage
+import com.android.systemui.util.kotlin.mapValuesNotNullTo
+
+/**
+ * An explicit storage for remembering composable state outside of the lifetime of a composition.
+ *
+ * Specifically, this allows easy conversion of standard
+ * [remember][androidx.compose.runtime.remember] invocations to ones that are preserved beyond the
+ * callsite's existence in the composition.
+ *
+ * ```kotlin
+ * @Composable
+ * fun Parent() {
+ * val session = remember { Session() }
+ * ...
+ * if (someCondition) {
+ * Child(session)
+ * }
+ * }
+ *
+ * @Composable
+ * fun Child(session: Session) {
+ * val state by session.rememberSession { mutableStateOf(0f) }
+ * ...
+ * }
+ * ```
+ */
+interface Session {
+ /**
+ * Remember the value returned by [init] if all [inputs] are equal (`==`) to the values they had
+ * in the previous composition, otherwise produce and remember a new value by calling [init].
+ *
+ * @param inputs A set of inputs such that, when any of them have changed, will cause the state
+ * to reset and [init] to be rerun
+ * @param key An optional key to be used as a key for the saved value. If `null`, we use the one
+ * automatically generated by the Compose runtime which is unique for the every exact code
+ * location in the composition tree
+ * @param init A factory function to create the initial value of this state
+ * @see androidx.compose.runtime.remember
+ */
+ @Composable fun <T> rememberSession(key: String?, vararg inputs: Any?, init: () -> T): T
+}
+
+/** Returns a new [Session], optionally backed by the provided [SessionStorage]. */
+fun Session(storage: SessionStorage = SessionStorage()): Session = SessionImpl(storage)
+
+/**
+ * Remember the value returned by [init] if all [inputs] are equal (`==`) to the values they had in
+ * the previous composition, otherwise produce and remember a new value by calling [init].
+ *
+ * @param inputs A set of inputs such that, when any of them have changed, will cause the state to
+ * reset and [init] to be rerun
+ * @param key An optional key to be used as a key for the saved value. If not provided we use the
+ * one automatically generated by the Compose runtime which is unique for the every exact code
+ * location in the composition tree
+ * @param init A factory function to create the initial value of this state
+ * @see androidx.compose.runtime.remember
+ */
+@Composable
+fun <T> Session.rememberSession(vararg inputs: Any?, key: String? = null, init: () -> T): T =
+ rememberSession(key, inputs, init = init)
+
+/**
+ * An explicit storage for remembering composable state outside of the lifetime of a composition.
+ *
+ * Specifically, this allows easy conversion of standard [rememberSession] invocations to ones that
+ * are preserved beyond the callsite's existence in the composition.
+ *
+ * ```kotlin
+ * @Composable
+ * fun Parent() {
+ * val session = rememberSaveableSession()
+ * ...
+ * if (someCondition) {
+ * Child(session)
+ * }
+ * }
+ *
+ * @Composable
+ * fun Child(session: SaveableSession) {
+ * val state by session.rememberSaveableSession { mutableStateOf(0f) }
+ * ...
+ * }
+ * ```
+ */
+interface SaveableSession : Session {
+ /**
+ * Remember the value produced by [init].
+ *
+ * It behaves similarly to [rememberSession], but the stored value will survive the activity or
+ * process recreation using the saved instance state mechanism (for example it happens when the
+ * screen is rotated in the Android application).
+ *
+ * @param inputs A set of inputs such that, when any of them have changed, will cause the state
+ * to reset and [init] to be rerun
+ * @param saver The [Saver] object which defines how the state is saved and restored.
+ * @param key An optional key to be used as a key for the saved value. If not provided we use
+ * the automatically generated by the Compose runtime which is unique for the every exact code
+ * location in the composition tree
+ * @param init A factory function to create the initial value of this state
+ * @see rememberSaveable
+ */
+ @Composable
+ fun <T : Any> rememberSaveableSession(
+ vararg inputs: Any?,
+ saver: Saver<T, out Any>,
+ key: String?,
+ init: () -> T,
+ ): T
+}
+
+/**
+ * Returns a new [SaveableSession] that is preserved across configuration changes.
+ *
+ * @param inputs A set of inputs such that, when any of them have changed, will cause the state to
+ * reset.
+ * @param key An optional key to be used as a key for the saved value. If not provided we use the
+ * automatically generated by the Compose runtime which is unique for the every exact code
+ * location in the composition tree.
+ */
+@Composable
+fun rememberSaveableSession(
+ vararg inputs: Any?,
+ key: String? = null,
+): SaveableSession =
+ rememberSaveable(inputs, SaveableSessionImpl.SessionSaver, key) { SaveableSessionImpl() }
+
+private class SessionImpl(
+ private val storage: SessionStorage = SessionStorage(),
+) : Session {
+ @Composable
+ override fun <T> rememberSession(key: String?, vararg inputs: Any?, init: () -> T): T {
+ val storage = storage.storage
+ val compositeKey = currentCompositeKeyHash
+ // key is the one provided by the user or the one generated by the compose runtime
+ val finalKey =
+ if (!key.isNullOrEmpty()) {
+ key
+ } else {
+ compositeKey.toString(MAX_SUPPORTED_RADIX)
+ }
+ if (finalKey !in storage) {
+ val value = init()
+ SideEffect { storage[finalKey] = SessionStorage.StorageEntry(inputs, value) }
+ return value
+ }
+ val entry = storage[finalKey]!!
+ if (!inputs.contentEquals(entry.keys)) {
+ val value = init()
+ SideEffect { entry.stored = value }
+ return value
+ }
+ @Suppress("UNCHECKED_CAST") return entry.stored as T
+ }
+}
+
+private class SaveableSessionImpl(
+ saveableStorage: MutableMap<String, StorageEntry> = mutableMapOf(),
+ sessionStorage: SessionStorage = SessionStorage(),
+) : SaveableSession, Session by Session(sessionStorage) {
+
+ var saveableStorage: MutableMap<String, StorageEntry> by mutableStateOf(saveableStorage)
+
+ @Composable
+ override fun <T : Any> rememberSaveableSession(
+ vararg inputs: Any?,
+ saver: Saver<T, out Any>,
+ key: String?,
+ init: () -> T,
+ ): T {
+ val compositeKey = currentCompositeKeyHash
+ // key is the one provided by the user or the one generated by the compose runtime
+ val finalKey =
+ if (!key.isNullOrEmpty()) {
+ key
+ } else {
+ compositeKey.toString(MAX_SUPPORTED_RADIX)
+ }
+
+ @Suppress("UNCHECKED_CAST") (saver as Saver<T, Any>)
+
+ if (finalKey !in saveableStorage) {
+ val value = init()
+ SideEffect { saveableStorage[finalKey] = StorageEntry.Restored(inputs, value, saver) }
+ return value
+ }
+ when (val entry = saveableStorage[finalKey]!!) {
+ is StorageEntry.Unrestored -> {
+ val value = saver.restore(entry.unrestored) ?: init()
+ SideEffect {
+ saveableStorage[finalKey] = StorageEntry.Restored(inputs, value, saver)
+ }
+ return value
+ }
+ is StorageEntry.Restored<*> -> {
+ if (!inputs.contentEquals(entry.inputs)) {
+ val value = init()
+ SideEffect {
+ saveableStorage[finalKey] = StorageEntry.Restored(inputs, value, saver)
+ }
+ return value
+ }
+ @Suppress("UNCHECKED_CAST") return entry.stored as T
+ }
+ }
+ }
+
+ sealed class StorageEntry {
+ class Unrestored(val unrestored: Any) : StorageEntry()
+
+ class Restored<T>(val inputs: Array<out Any?>, var stored: T, val saver: Saver<T, Any>) :
+ StorageEntry() {
+ fun SaverScope.saveEntry() {
+ with(saver) { stored?.let { save(it) } }
+ }
+ }
+ }
+
+ object SessionSaver :
+ Saver<SaveableSessionImpl, Any> by mapSaver(
+ save = { sessionScope: SaveableSessionImpl ->
+ sessionScope.saveableStorage.mapValues { (k, v) ->
+ when (v) {
+ is StorageEntry.Unrestored -> v.unrestored
+ is StorageEntry.Restored<*> -> {
+ with(v) { saveEntry() }
+ }
+ }
+ }
+ },
+ restore = { savedMap: Map<String, Any?> ->
+ SaveableSessionImpl(
+ saveableStorage =
+ savedMap.mapValuesNotNullTo(mutableMapOf()) { (k, v) ->
+ v?.let { StorageEntry.Unrestored(v) }
+ }
+ )
+ }
+ )
+}
+
+private const val MAX_SUPPORTED_RADIX = 36
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt
index 4c656b0..7eaebc2 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt
@@ -5,7 +5,6 @@
import com.android.systemui.bouncer.ui.composable.Bouncer
import com.android.systemui.notifications.ui.composable.Notifications
import com.android.systemui.scene.shared.model.Scenes
-import com.android.systemui.scene.shared.model.TransitionKeys.CollapseShadeInstantly
import com.android.systemui.scene.shared.model.TransitionKeys.SlightlyFasterShadeCollapse
import com.android.systemui.scene.ui.composable.transitions.bouncerToGoneTransition
import com.android.systemui.scene.ui.composable.transitions.goneToQuickSettingsTransition
@@ -16,6 +15,7 @@
import com.android.systemui.scene.ui.composable.transitions.lockscreenToQuickSettingsTransition
import com.android.systemui.scene.ui.composable.transitions.lockscreenToShadeTransition
import com.android.systemui.scene.ui.composable.transitions.shadeToQuickSettingsTransition
+import com.android.systemui.shade.ui.composable.Shade
/**
* Comprehensive definition of all transitions between scenes in [SceneContainer].
@@ -38,13 +38,6 @@
from(
Scenes.Gone,
to = Scenes.Shade,
- key = CollapseShadeInstantly,
- ) {
- goneToShadeTransition(durationScale = 0.0)
- }
- from(
- Scenes.Gone,
- to = Scenes.Shade,
key = SlightlyFasterShadeCollapse,
) {
goneToShadeTransition(durationScale = 0.9)
@@ -56,13 +49,6 @@
from(
Scenes.Lockscreen,
to = Scenes.Shade,
- key = CollapseShadeInstantly,
- ) {
- lockscreenToShadeTransition(durationScale = 0.0)
- }
- from(
- Scenes.Lockscreen,
- to = Scenes.Shade,
key = SlightlyFasterShadeCollapse,
) {
lockscreenToShadeTransition(durationScale = 0.9)
@@ -73,10 +59,14 @@
// Scene overscroll
+ overscroll(Scenes.Gone, Orientation.Vertical) {}
overscroll(Scenes.Bouncer, Orientation.Vertical) {
translate(Bouncer.Elements.Content, y = { absoluteDistance })
}
overscroll(Scenes.Shade, Orientation.Vertical) {
- translate(Notifications.Elements.NotificationScrim, y = { absoluteDistance })
+ translate(
+ Notifications.Elements.NotificationScrim,
+ y = { Shade.Dimensions.ScrimOverscrollLimit }
+ )
}
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneTransitionLayoutDataSource.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneTransitionLayoutDataSource.kt
index a54994d..4b4b7ed 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneTransitionLayoutDataSource.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneTransitionLayoutDataSource.kt
@@ -19,7 +19,6 @@
package com.android.systemui.scene.ui.composable
import com.android.compose.animation.scene.MutableSceneTransitionLayoutState
-import com.android.compose.animation.scene.ObservableTransitionState
import com.android.compose.animation.scene.SceneKey
import com.android.compose.animation.scene.TransitionKey
import com.android.compose.animation.scene.observableTransitionState
@@ -29,8 +28,6 @@
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.flatMapLatest
-import kotlinx.coroutines.flow.flowOf
-import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
/**
@@ -48,19 +45,7 @@
override val currentScene: StateFlow<SceneKey> =
state
.observableTransitionState()
- .flatMapLatest { observableTransitionState ->
- when (observableTransitionState) {
- is ObservableTransitionState.Idle -> flowOf(observableTransitionState.scene)
- is ObservableTransitionState.Transition ->
- observableTransitionState.isUserInputOngoing.map { isUserInputOngoing ->
- if (isUserInputOngoing) {
- observableTransitionState.fromScene
- } else {
- observableTransitionState.toScene
- }
- }
- }
- }
+ .flatMapLatest { it.currentScene() }
.stateIn(
scope = coroutineScope,
started = SharingStarted.WhileSubscribed(),
@@ -77,4 +62,10 @@
coroutineScope = coroutineScope,
)
}
+
+ override fun snapToScene(toScene: SceneKey) {
+ state.snapToScene(
+ scene = toScene,
+ )
+ }
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromGoneToQuickSettingsTransition.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromGoneToQuickSettingsTransition.kt
index 851719d..918e1ad 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromGoneToQuickSettingsTransition.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromGoneToQuickSettingsTransition.kt
@@ -1,14 +1,12 @@
package com.android.systemui.scene.ui.composable.transitions
-import androidx.compose.animation.core.tween
import com.android.compose.animation.scene.TransitionBuilder
import kotlin.time.Duration.Companion.milliseconds
fun TransitionBuilder.goneToQuickSettingsTransition(
durationScale: Double = 1.0,
) {
- spec = tween(durationMillis = (DefaultDuration * durationScale).inWholeMilliseconds.toInt())
- toQuickSettingsTransition()
+ toQuickSettingsTransition(durationScale = durationScale)
}
private val DefaultDuration = 500.milliseconds
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromGoneToShadeTransition.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromGoneToShadeTransition.kt
index a0f410a..d3ef273 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromGoneToShadeTransition.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromGoneToShadeTransition.kt
@@ -1,14 +1,9 @@
package com.android.systemui.scene.ui.composable.transitions
-import androidx.compose.animation.core.tween
import com.android.compose.animation.scene.TransitionBuilder
-import kotlin.time.Duration.Companion.milliseconds
fun TransitionBuilder.goneToShadeTransition(
durationScale: Double = 1.0,
) {
- spec = tween(durationMillis = (DefaultDuration * durationScale).inWholeMilliseconds.toInt())
- toShadeTransition()
+ toShadeTransition(durationScale = durationScale)
}
-
-private val DefaultDuration = 500.milliseconds
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToQuickSettingsTransition.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToQuickSettingsTransition.kt
index 319438c..ba30a85 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToQuickSettingsTransition.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToQuickSettingsTransition.kt
@@ -1,14 +1,9 @@
package com.android.systemui.scene.ui.composable.transitions
-import androidx.compose.animation.core.tween
import com.android.compose.animation.scene.TransitionBuilder
-import kotlin.time.Duration.Companion.milliseconds
fun TransitionBuilder.lockscreenToQuickSettingsTransition(
durationScale: Double = 1.0,
) {
- spec = tween(durationMillis = (DefaultDuration * durationScale).inWholeMilliseconds.toInt())
- toQuickSettingsTransition()
+ toQuickSettingsTransition(durationScale = durationScale)
}
-
-private val DefaultDuration = 500.milliseconds
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToShadeTransition.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToShadeTransition.kt
index f078b8c..2aded0d 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToShadeTransition.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToShadeTransition.kt
@@ -1,14 +1,9 @@
package com.android.systemui.scene.ui.composable.transitions
-import androidx.compose.animation.core.tween
import com.android.compose.animation.scene.TransitionBuilder
-import kotlin.time.Duration.Companion.milliseconds
fun TransitionBuilder.lockscreenToShadeTransition(
durationScale: Double = 1.0,
) {
- spec = tween(durationMillis = (DefaultDuration * durationScale).inWholeMilliseconds.toInt())
- toShadeTransition()
+ toShadeTransition(durationScale = durationScale)
}
-
-private val DefaultDuration = 500.milliseconds
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromShadeToQuickSettingsTransition.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromShadeToQuickSettingsTransition.kt
index a9e5be9..8cd357e 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromShadeToQuickSettingsTransition.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromShadeToQuickSettingsTransition.kt
@@ -1,10 +1,15 @@
package com.android.systemui.scene.ui.composable.transitions
import androidx.compose.animation.core.tween
+import androidx.compose.foundation.gestures.Orientation
+import androidx.compose.ui.unit.IntSize
import com.android.compose.animation.scene.Edge
import com.android.compose.animation.scene.TransitionBuilder
+import com.android.compose.animation.scene.UserActionDistance
+import com.android.compose.animation.scene.UserActionDistanceScope
import com.android.systemui.notifications.ui.composable.Notifications
import com.android.systemui.qs.ui.composable.QuickSettings
+import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.shade.ui.composable.ShadeHeader
import kotlin.time.Duration.Companion.milliseconds
@@ -12,6 +17,18 @@
durationScale: Double = 1.0,
) {
spec = tween(durationMillis = (DefaultDuration * durationScale).inWholeMilliseconds.toInt())
+ distance =
+ object : UserActionDistance {
+ override fun UserActionDistanceScope.absoluteDistance(
+ fromSceneSize: IntSize,
+ orientation: Orientation,
+ ): Float {
+ val distance =
+ Notifications.Elements.NotificationScrim.targetOffset(Scenes.Shade)?.y
+ ?: return 0f
+ return fromSceneSize.height - distance
+ }
+ }
translate(Notifications.Elements.NotificationScrim, Edge.Bottom)
timestampRange(endMillis = 83) { fade(QuickSettings.Elements.FooterActions) }
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/ToShadeTransition.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/ToShadeTransition.kt
index 2f59217..df47cba 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/ToShadeTransition.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/ToShadeTransition.kt
@@ -16,11 +16,19 @@
package com.android.systemui.scene.ui.composable.transitions
+import androidx.compose.animation.core.Spring
+import androidx.compose.animation.core.spring
import androidx.compose.animation.core.tween
+import androidx.compose.foundation.gestures.Orientation
+import androidx.compose.ui.unit.IntSize
import com.android.compose.animation.scene.Edge
import com.android.compose.animation.scene.TransitionBuilder
+import com.android.compose.animation.scene.UserActionDistance
+import com.android.compose.animation.scene.UserActionDistanceScope
import com.android.systemui.notifications.ui.composable.Notifications
import com.android.systemui.qs.ui.composable.QuickSettings
+import com.android.systemui.scene.shared.model.Scenes
+import com.android.systemui.shade.ui.composable.Shade
import com.android.systemui.shade.ui.composable.ShadeHeader
import kotlin.time.Duration.Companion.milliseconds
@@ -28,6 +36,20 @@
durationScale: Double = 1.0,
) {
spec = tween(durationMillis = (DefaultDuration * durationScale).inWholeMilliseconds.toInt())
+ swipeSpec =
+ spring(
+ stiffness = Spring.StiffnessMediumLow,
+ visibilityThreshold = Shade.Dimensions.ScrimVisibilityThreshold,
+ )
+ distance =
+ object : UserActionDistance {
+ override fun UserActionDistanceScope.absoluteDistance(
+ fromSceneSize: IntSize,
+ orientation: Orientation,
+ ): Float {
+ return Notifications.Elements.NotificationScrim.targetOffset(Scenes.Shade)?.y ?: 0f
+ }
+ }
fractionRange(start = .58f) {
fade(ShadeHeader.Elements.Clock)
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/OverlayShade.kt b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/OverlayShade.kt
new file mode 100644
index 0000000..d528736
--- /dev/null
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/OverlayShade.kt
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shade.ui.composable
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.ReadOnlyComposable
+import androidx.compose.runtime.collectAsState
+import androidx.compose.runtime.getValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.unit.dp
+import com.android.compose.animation.scene.ElementKey
+import com.android.compose.animation.scene.LowestZIndexScenePicker
+import com.android.compose.animation.scene.SceneScope
+import com.android.systemui.scene.shared.model.Scenes
+import com.android.systemui.shade.ui.viewmodel.OverlayShadeViewModel
+
+/** The overlay shade renders a lightweight shade UI container on top of a background scene. */
+@Composable
+fun SceneScope.OverlayShade(
+ viewModel: OverlayShadeViewModel,
+ horizontalArrangement: Arrangement.Horizontal,
+ modifier: Modifier = Modifier,
+ content: @Composable () -> Unit,
+) {
+ val backgroundScene by viewModel.backgroundScene.collectAsState()
+
+ Box(modifier) {
+ if (backgroundScene == Scenes.Lockscreen) {
+ Lockscreen()
+ }
+
+ Scrim(onClicked = viewModel::onScrimClicked)
+
+ Row(
+ modifier = Modifier.fillMaxSize().padding(OverlayShade.Dimensions.ScrimContentPadding),
+ horizontalArrangement = horizontalArrangement,
+ ) {
+ Panel(content = content)
+ }
+ }
+}
+
+@Composable
+private fun Lockscreen(
+ modifier: Modifier = Modifier,
+) {
+ // TODO(b/338025605): This is a placeholder, replace with the actual lockscreen.
+ Box(modifier = modifier.fillMaxSize().background(Color.LightGray)) {
+ Text(text = "Lockscreen", modifier = Modifier.align(Alignment.Center))
+ }
+}
+
+@Composable
+private fun SceneScope.Scrim(
+ onClicked: () -> Unit,
+ modifier: Modifier = Modifier,
+) {
+ Spacer(
+ modifier =
+ modifier
+ .element(OverlayShade.Elements.Scrim)
+ .fillMaxSize()
+ .background(OverlayShade.Colors.ScrimBackground)
+ .clickable(onClick = onClicked, interactionSource = null, indication = null)
+ )
+}
+
+@Composable
+private fun SceneScope.Panel(
+ modifier: Modifier = Modifier,
+ content: @Composable () -> Unit,
+) {
+ Box(
+ modifier =
+ modifier
+ .width(OverlayShade.Dimensions.PanelWidth)
+ .clip(OverlayShade.Shapes.RoundedCornerPanel)
+ ) {
+ Spacer(
+ modifier =
+ Modifier.element(OverlayShade.Elements.PanelBackground)
+ .matchParentSize()
+ .background(
+ color = OverlayShade.Colors.PanelBackground,
+ shape = OverlayShade.Shapes.RoundedCornerPanel,
+ ),
+ )
+
+ // This content is intentionally rendered as a separate element from the background in order
+ // to allow for more flexibility when defining transitions.
+ content()
+ }
+}
+
+object OverlayShade {
+ object Elements {
+ val Scrim = ElementKey("OverlayShadeScrim", scenePicker = LowestZIndexScenePicker)
+ val PanelBackground =
+ ElementKey("OverlayShadePanelBackground", scenePicker = LowestZIndexScenePicker)
+ }
+
+ object Colors {
+ val ScrimBackground = Color(0, 0, 0, alpha = 255 / 3)
+ val PanelBackground: Color
+ @Composable @ReadOnlyComposable get() = MaterialTheme.colorScheme.surfaceContainer
+ }
+
+ object Dimensions {
+ val ScrimContentPadding = 16.dp
+ val PanelCornerRadius = 46.dp
+ // TODO(b/338033836): This width should not be fixed.
+ val PanelWidth = 390.dp
+ }
+
+ object Shapes {
+ val RoundedCornerPanel = RoundedCornerShape(Dimensions.PanelCornerRadius)
+ }
+}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt
index d3b3d15..0bd38a1 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt
@@ -63,6 +63,7 @@
import com.android.systemui.battery.BatteryMeterViewController
import com.android.systemui.common.ui.compose.windowinsets.CutoutLocation
import com.android.systemui.common.ui.compose.windowinsets.LocalDisplayCutout
+import com.android.systemui.compose.modifiers.sysuiResTag
import com.android.systemui.privacy.OngoingPrivacyChip
import com.android.systemui.res.R
import com.android.systemui.scene.shared.model.Scenes
@@ -100,6 +101,10 @@
val ColorScheme.shadeHeaderText: Color
get() = Color.White
}
+
+ object TestTags {
+ const val Root = "shade_header_root"
+ }
}
@Composable
@@ -131,7 +136,7 @@
// This layout assumes it is globally positioned at (0, 0) and is the
// same size as the screen.
Layout(
- modifier = modifier,
+ modifier = modifier.sysuiResTag(ShadeHeader.TestTags.Root),
contents =
listOf(
{
@@ -261,7 +266,7 @@
val isPrivacyChipVisible by viewModel.isPrivacyChipVisible.collectAsState()
- Box(modifier = modifier) {
+ Box(modifier = modifier.sysuiResTag(ShadeHeader.TestTags.Root)) {
if (isPrivacyChipVisible) {
Box(modifier = Modifier.height(CollapsedHeight).fillMaxWidth()) {
PrivacyChip(
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt
index cda8059..4ad8b9f 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt
@@ -17,7 +17,9 @@
package com.android.systemui.shade.ui.composable
import android.view.ViewGroup
+import androidx.compose.animation.core.animateDpAsState
import androidx.compose.animation.core.animateFloatAsState
+import androidx.compose.animation.core.tween
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.clipScrollableContainer
@@ -40,6 +42,7 @@
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
@@ -76,6 +79,7 @@
import com.android.systemui.qs.ui.composable.BrightnessMirror
import com.android.systemui.qs.ui.composable.QuickSettings
import com.android.systemui.res.R
+import com.android.systemui.scene.session.ui.composable.SaveableSession
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.ui.composable.ComposableScene
import com.android.systemui.shade.shared.model.ShadeMode
@@ -98,6 +102,8 @@
object Dimensions {
val ScrimCornerSize = 32.dp
val HorizontalPadding = 16.dp
+ const val ScrimOverscrollLimit = 100f
+ const val ScrimVisibilityThreshold = 5f
}
object Shapes {
@@ -114,6 +120,7 @@
class ShadeScene
@Inject
constructor(
+ private val shadeSession: SaveableSession,
private val viewModel: ShadeSceneViewModel,
private val tintedIconManagerFactory: TintedIconManager.Factory,
private val batteryMeterViewControllerFactory: BatteryMeterViewController.Factory,
@@ -121,6 +128,7 @@
private val mediaCarouselController: MediaCarouselController,
@Named(QUICK_QS_PANEL) private val mediaHost: MediaHost,
) : ComposableScene {
+
override val key = Scenes.Shade
override val destinationScenes: StateFlow<Map<UserAction, UserActionResult>> =
@@ -138,6 +146,7 @@
mediaCarouselController = mediaCarouselController,
mediaHost = mediaHost,
modifier = modifier,
+ shadeSession = shadeSession,
)
init {
@@ -156,6 +165,7 @@
mediaCarouselController: MediaCarouselController,
mediaHost: MediaHost,
modifier: Modifier = Modifier,
+ shadeSession: SaveableSession,
) {
val shadeMode by viewModel.shadeMode.collectAsState()
when (shadeMode) {
@@ -168,6 +178,7 @@
mediaCarouselController = mediaCarouselController,
mediaHost = mediaHost,
modifier = modifier,
+ shadeSession = shadeSession,
)
is ShadeMode.Split ->
SplitShade(
@@ -178,6 +189,7 @@
mediaCarouselController = mediaCarouselController,
mediaHost = mediaHost,
modifier = modifier,
+ shadeSession = shadeSession,
)
is ShadeMode.Dual -> error("Dual shade is not yet implemented!")
}
@@ -192,15 +204,30 @@
mediaCarouselController: MediaCarouselController,
mediaHost: MediaHost,
modifier: Modifier = Modifier,
+ shadeSession: SaveableSession,
) {
val maxNotifScrimTop = remember { mutableStateOf(0f) }
val tileSquishiness by
- animateSceneFloatAsState(value = 1f, key = QuickSettings.SharedValues.TilesSquishiness)
+ animateSceneFloatAsState(
+ value = 1f,
+ key = QuickSettings.SharedValues.TilesSquishiness,
+ canOverflow = false
+ )
val isClickable by viewModel.isClickable.collectAsState()
- // Render the scene to an offscreen buffer so that BlendMode.DstOut only clears this scene
- // (and not the one under it) during a scene transition.
- Box(modifier = modifier.graphicsLayer(compositingStrategy = CompositingStrategy.Offscreen)) {
+ val shouldPunchHoleBehindScrim =
+ layoutState.isTransitioningBetween(Scenes.Gone, Scenes.Shade) ||
+ layoutState.isTransitioningBetween(Scenes.Lockscreen, Scenes.Shade)
+
+ Box(
+ modifier =
+ modifier.thenIf(shouldPunchHoleBehindScrim) {
+ // Render the scene to an offscreen buffer so that BlendMode.DstOut only clears this
+ // scene
+ // (and not the one under it) during a scene transition.
+ Modifier.graphicsLayer(compositingStrategy = CompositingStrategy.Offscreen)
+ }
+ ) {
Box(
modifier =
Modifier.fillMaxSize()
@@ -231,10 +258,7 @@
Box(Modifier.element(QuickSettings.Elements.QuickQuickSettings)) {
QuickSettings(
viewModel.qsSceneAdapter,
- {
- (viewModel.qsSceneAdapter.qqsHeight * tileSquishiness)
- .roundToInt()
- },
+ { viewModel.qsSceneAdapter.qqsHeight },
isSplitShade = false,
squishiness = tileSquishiness,
)
@@ -252,8 +276,10 @@
},
{
NotificationScrollingStack(
+ shadeSession = shadeSession,
viewModel = viewModel.notifications,
maxScrimTop = { maxNotifScrimTop.value },
+ shouldPunchHoleBehindScrim = shouldPunchHoleBehindScrim,
)
},
)
@@ -284,8 +310,12 @@
mediaCarouselController: MediaCarouselController,
mediaHost: MediaHost,
modifier: Modifier = Modifier,
+ shadeSession: SaveableSession,
) {
val isCustomizing by viewModel.qsSceneAdapter.isCustomizing.collectAsState()
+ val isCustomizerShowing by viewModel.qsSceneAdapter.isCustomizerShowing.collectAsState()
+ val customizingAnimationDuration by
+ viewModel.qsSceneAdapter.customizerAnimationDuration.collectAsState()
val lifecycleOwner = LocalLifecycleOwner.current
val footerActionsViewModel =
remember(lifecycleOwner, viewModel) { viewModel.getFooterActionsViewModel(lifecycleOwner) }
@@ -305,6 +335,12 @@
.collectAsState(0f)
val navBarBottomHeight = WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding()
+ val bottomPadding by
+ animateDpAsState(
+ targetValue = if (isCustomizing) 0.dp else navBarBottomHeight,
+ animationSpec = tween(customizingAnimationDuration),
+ label = "animateQSSceneBottomPaddingAsState"
+ )
val density = LocalDensity.current
LaunchedEffect(navBarBottomHeight, density) {
with(density) {
@@ -327,6 +363,9 @@
label = "alphaAnimationBrightnessMirrorContentHiding",
)
+ viewModel.notifications.setAlphaForBrightnessMirror(contentAlpha)
+ DisposableEffect(Unit) { onDispose { viewModel.notifications.setAlphaForBrightnessMirror(1f) } }
+
val brightnessMirrorShowingModifier = Modifier.graphicsLayer { alpha = contentAlpha }
Box(
@@ -372,16 +411,13 @@
)
Column(
verticalArrangement = Arrangement.Top,
- modifier =
- Modifier.fillMaxSize().thenIf(!isCustomizing) {
- Modifier.padding(bottom = navBarBottomHeight)
- },
+ modifier = Modifier.fillMaxSize().padding(bottom = bottomPadding),
) {
Column(
modifier =
Modifier.fillMaxSize()
.weight(1f)
- .thenIf(!isCustomizing) {
+ .thenIf(!isCustomizerShowing) {
Modifier.verticalNestedScrollToScene()
.verticalScroll(
quickSettingsScrollState,
@@ -414,6 +450,7 @@
FooterActionsWithAnimatedVisibility(
viewModel = footerActionsViewModel,
isCustomizing = isCustomizing,
+ customizingAnimationDuration = customizingAnimationDuration,
lifecycleOwner = lifecycleOwner,
modifier =
Modifier.align(Alignment.CenterHorizontally)
@@ -423,8 +460,10 @@
}
NotificationScrollingStack(
+ shadeSession = shadeSession,
viewModel = viewModel.notifications,
maxScrimTop = { 0f },
+ shouldPunchHoleBehindScrim = false,
modifier =
Modifier.weight(1f)
.fillMaxHeight()
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/anc/ui/composable/AncButtonComponent.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/anc/ui/composable/AncButtonComponent.kt
index 00225fc..79d17ef 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/anc/ui/composable/AncButtonComponent.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/anc/ui/composable/AncButtonComponent.kt
@@ -16,6 +16,7 @@
package com.android.systemui.volume.panel.component.anc.ui.composable
+import androidx.compose.foundation.basicMarquee
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
@@ -35,7 +36,6 @@
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.role
import androidx.compose.ui.semantics.semantics
-import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import com.android.systemui.res.R
import com.android.systemui.volume.panel.component.anc.ui.viewmodel.AncViewModel
@@ -54,6 +54,13 @@
override fun VolumePanelComposeScope.Content(modifier: Modifier) {
val slice by viewModel.buttonSlice.collectAsState()
val label = stringResource(R.string.volume_panel_noise_control_title)
+ val isClickable = viewModel.isClickable(slice)
+ val onClick =
+ if (isClickable) {
+ { ancPopup.show(null) }
+ } else {
+ null
+ }
Column(
modifier = modifier,
verticalArrangement = Arrangement.spacedBy(12.dp),
@@ -69,15 +76,15 @@
}
.clip(RoundedCornerShape(28.dp)),
slice = slice,
+ isEnabled = onClick != null,
onWidthChanged = viewModel::onButtonSliceWidthChanged,
- onClick = { ancPopup.show(null) }
+ onClick = onClick,
)
Text(
- modifier = Modifier.clearAndSetSemantics {},
+ modifier = Modifier.clearAndSetSemantics {}.basicMarquee(),
text = label,
style = MaterialTheme.typography.labelMedium,
- maxLines = 1,
- overflow = TextOverflow.Ellipsis,
+ maxLines = 2,
)
}
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/anc/ui/composable/SliceAndroidView.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/anc/ui/composable/SliceAndroidView.kt
index 74af3ca..fc5d212 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/anc/ui/composable/SliceAndroidView.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/anc/ui/composable/SliceAndroidView.kt
@@ -32,6 +32,7 @@
fun SliceAndroidView(
slice: Slice?,
modifier: Modifier = Modifier,
+ isEnabled: Boolean = true,
onWidthChanged: ((Int) -> Unit)? = null,
onClick: (() -> Unit)? = null,
) {
@@ -40,7 +41,6 @@
factory = { context: Context ->
ClickableSliceView(
ContextThemeWrapper(context, R.style.Widget_SliceView_VolumePanel),
- onClick,
)
.apply {
mode = SliceView.MODE_LARGE
@@ -50,12 +50,14 @@
if (onWidthChanged != null) {
addOnLayoutChangeListener(OnWidthChangedLayoutListener(onWidthChanged))
}
- if (onClick != null) {
- setOnClickListener { onClick() }
- }
}
},
- update = { sliceView: SliceView -> sliceView.slice = slice }
+ update = { sliceView: ClickableSliceView ->
+ sliceView.slice = slice
+ sliceView.onClick = onClick
+ sliceView.isEnabled = isEnabled
+ sliceView.isClickable = isEnabled
+ }
)
}
@@ -86,10 +88,9 @@
* first.
*/
@SuppressLint("ViewConstructor") // only used in this class
-private class ClickableSliceView(
- context: Context,
- private val onClick: (() -> Unit)?,
-) : SliceView(context) {
+private class ClickableSliceView(context: Context) : SliceView(context) {
+
+ var onClick: (() -> Unit)? = null
init {
if (onClick != null) {
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/button/ui/composable/ToggleButtonComponent.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/button/ui/composable/ToggleButtonComponent.kt
index 874c0a2..12debbc 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/button/ui/composable/ToggleButtonComponent.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/button/ui/composable/ToggleButtonComponent.kt
@@ -19,6 +19,7 @@
import androidx.compose.foundation.basicMarquee
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
@@ -91,7 +92,8 @@
},
onClick = { onCheckedChange(!viewModel.isActive) },
shape = RoundedCornerShape(28.dp),
- colors = colors
+ colors = colors,
+ contentPadding = PaddingValues(0.dp)
) {
Icon(modifier = Modifier.size(24.dp), icon = viewModel.icon)
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/mediaoutput/MediaOutputModule.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/mediaoutput/MediaOutputModule.kt
index c73656e..f1cc71b 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/mediaoutput/MediaOutputModule.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/mediaoutput/MediaOutputModule.kt
@@ -16,9 +16,9 @@
package com.android.systemui.volume.panel.component.mediaoutput
-import com.android.systemui.volume.panel.component.mediaoutput.domain.MediaOutputAvailabilityCriteria
import com.android.systemui.volume.panel.component.mediaoutput.ui.composable.MediaOutputComponent
import com.android.systemui.volume.panel.component.shared.model.VolumePanelComponents
+import com.android.systemui.volume.panel.domain.AlwaysAvailableCriteria
import com.android.systemui.volume.panel.domain.ComponentAvailabilityCriteria
import com.android.systemui.volume.panel.shared.model.VolumePanelUiComponent
import dagger.Binds
@@ -39,6 +39,6 @@
@IntoMap
@StringKey(VolumePanelComponents.MEDIA_OUTPUT)
fun bindComponentAvailabilityCriteria(
- criteria: MediaOutputAvailabilityCriteria
+ criteria: AlwaysAvailableCriteria
): ComponentAvailabilityCriteria
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/mediaoutput/ui/composable/MediaOutputComponent.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/mediaoutput/ui/composable/MediaOutputComponent.kt
index 6f2ed81..ded63a1 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/mediaoutput/ui/composable/MediaOutputComponent.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/mediaoutput/ui/composable/MediaOutputComponent.kt
@@ -86,7 +86,10 @@
modifier =
Modifier.fillMaxWidth().height(80.dp).semantics {
liveRegion = LiveRegionMode.Polite
- this.onClick(label = clickLabel) { false }
+ this.onClick(label = clickLabel) {
+ viewModel.onBarClick(null)
+ true
+ }
},
color = MaterialTheme.colorScheme.surface,
shape = RoundedCornerShape(28.dp),
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/VolumeSlider.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/VolumeSlider.kt
index 9f5ab3c..a46f4e5 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/VolumeSlider.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/VolumeSlider.kt
@@ -66,7 +66,9 @@
// provide a not animated value to the a11y because it fails to announce the
// settled value when it changes rapidly.
- progressBarRangeInfo = ProgressBarRangeInfo(state.value, state.valueRange)
+ if (state.isEnabled) {
+ progressBarRangeInfo = ProgressBarRangeInfo(state.value, state.valueRange)
+ }
setProgress { targetValue ->
val targetDirection =
when {
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/ui/composable/VolumePanelRoot.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/ui/composable/VolumePanelRoot.kt
index c51e8b0..a602e25 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/ui/composable/VolumePanelRoot.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/ui/composable/VolumePanelRoot.kt
@@ -28,7 +28,11 @@
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.semantics.paneTitle
+import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.dp
+import com.android.systemui.res.R
import com.android.systemui.volume.panel.ui.layout.ComponentsLayout
import com.android.systemui.volume.panel.ui.viewmodel.VolumePanelState
import com.android.systemui.volume.panel.ui.viewmodel.VolumePanelViewModel
@@ -49,6 +53,7 @@
}
}
+ val accessibilityTitle = stringResource(R.string.accessibility_volume_settings)
val state: VolumePanelState by viewModel.volumePanelState.collectAsState()
val components by viewModel.componentsLayout.collectAsState(null)
@@ -56,12 +61,14 @@
components?.let { componentsState ->
Components(
componentsState,
- modifier.padding(
- start = padding,
- top = padding,
- end = padding,
- bottom = 20.dp,
- )
+ modifier
+ .semantics { paneTitle = accessibilityTitle }
+ .padding(
+ start = padding,
+ top = padding,
+ end = padding,
+ bottom = 20.dp,
+ )
)
}
}
diff --git a/packages/SystemUI/compose/scene/OWNERS b/packages/SystemUI/compose/scene/OWNERS
index 33a59c2..dac37ee 100644
--- a/packages/SystemUI/compose/scene/OWNERS
+++ b/packages/SystemUI/compose/scene/OWNERS
@@ -2,12 +2,13 @@
# Bug component: 1184816
+amiko@google.com
jdemeulenaere@google.com
omarmt@google.com
# SysUI Dr No's.
# Don't send reviews here.
-dsandler@android.com
cinek@google.com
+dsandler@android.com
juliacr@google.com
pixel@google.com
\ No newline at end of file
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateToScene.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateToScene.kt
index 6b289f3..b5e9313 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateToScene.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateToScene.kt
@@ -47,8 +47,11 @@
}
return when (transitionState) {
- is TransitionState.Idle -> animate(layoutState, target, transitionKey)
+ is TransitionState.Idle ->
+ animate(layoutState, target, transitionKey, isInitiatedByUserInput = false)
is TransitionState.Transition -> {
+ val isInitiatedByUserInput = transitionState.isInitiatedByUserInput
+
// A transition is currently running: first check whether `transition.toScene` or
// `transition.fromScene` is the same as our target scene, in which case the transition
// can be accelerated or reversed to end up in the target state.
@@ -68,8 +71,14 @@
} else {
// The transition is in progress: start the canned animation at the same
// progress as it was in.
- // TODO(b/290184746): Also take the current velocity into account.
- animate(layoutState, target, transitionKey, startProgress = progress)
+ animate(
+ layoutState,
+ target,
+ transitionKey,
+ isInitiatedByUserInput,
+ initialProgress = progress,
+ initialVelocity = transitionState.progressVelocity,
+ )
}
} else if (transitionState.fromScene == target) {
// There is a transition from [target] to another scene: simply animate the same
@@ -83,19 +92,52 @@
layoutState.finishTransition(transitionState, target)
null
} else {
- // TODO(b/290184746): Also take the current velocity into account.
animate(
layoutState,
target,
transitionKey,
- startProgress = progress,
+ isInitiatedByUserInput,
+ initialProgress = progress,
+ initialVelocity = transitionState.progressVelocity,
reversed = true,
)
}
} else {
// Generic interruption; the current transition is neither from or to [target].
- // TODO(b/290930950): Better handle interruptions here.
- animate(layoutState, target, transitionKey)
+ val interruptionResult =
+ layoutState.transitions.interruptionHandler.onInterruption(
+ transitionState,
+ target,
+ )
+ ?: DefaultInterruptionHandler.onInterruption(transitionState, target)
+
+ val animateFrom = interruptionResult.animateFrom
+ if (
+ animateFrom != transitionState.toScene &&
+ animateFrom != transitionState.fromScene
+ ) {
+ error(
+ "InterruptionResult.animateFrom must be either the fromScene " +
+ "(${transitionState.fromScene.debugName}) or the toScene " +
+ "(${transitionState.toScene.debugName}) of the interrupted transition."
+ )
+ }
+
+ // If we were A => B and that we are now animating A => C, add a transition B => A
+ // to the list of transitions so that B "disappears back to A".
+ val chain = interruptionResult.chain
+ if (chain && animateFrom != transitionState.currentScene) {
+ animateToScene(layoutState, animateFrom, transitionKey = null)
+ }
+
+ animate(
+ layoutState,
+ target,
+ transitionKey,
+ isInitiatedByUserInput,
+ fromScene = animateFrom,
+ chain = chain,
+ )
}
}
}
@@ -103,32 +145,31 @@
private fun CoroutineScope.animate(
layoutState: BaseSceneTransitionLayoutState,
- target: SceneKey,
+ targetScene: SceneKey,
transitionKey: TransitionKey?,
- startProgress: Float = 0f,
+ isInitiatedByUserInput: Boolean,
+ initialProgress: Float = 0f,
+ initialVelocity: Float = 0f,
reversed: Boolean = false,
+ fromScene: SceneKey = layoutState.transitionState.currentScene,
+ chain: Boolean = true,
): TransitionState.Transition {
- val fromScene = layoutState.transitionState.currentScene
- val isUserInput =
- (layoutState.transitionState as? TransitionState.Transition)?.isInitiatedByUserInput
- ?: false
-
val targetProgress = if (reversed) 0f else 1f
val transition =
if (reversed) {
OneOffTransition(
- fromScene = target,
+ fromScene = targetScene,
toScene = fromScene,
- currentScene = target,
- isInitiatedByUserInput = isUserInput,
+ currentScene = targetScene,
+ isInitiatedByUserInput = isInitiatedByUserInput,
isUserInputOngoing = false,
)
} else {
OneOffTransition(
fromScene = fromScene,
- toScene = target,
- currentScene = target,
- isInitiatedByUserInput = isUserInput,
+ toScene = targetScene,
+ currentScene = targetScene,
+ isInitiatedByUserInput = isInitiatedByUserInput,
isUserInputOngoing = false,
)
}
@@ -136,7 +177,7 @@
// Change the current layout state to start this new transition. This will compute the
// TransformationSpec associated to this transition, which we need to initialize the Animatable
// that will actually animate it.
- layoutState.startTransition(transition, transitionKey)
+ layoutState.startTransition(transition, transitionKey, chain)
// The transition now contains the transformation spec that we should use to instantiate the
// Animatable.
@@ -144,19 +185,19 @@
val visibilityThreshold =
(animationSpec as? SpringSpec)?.visibilityThreshold ?: ProgressVisibilityThreshold
val animatable =
- Animatable(startProgress, visibilityThreshold = visibilityThreshold).also {
+ Animatable(initialProgress, visibilityThreshold = visibilityThreshold).also {
transition.animatable = it
}
// Animate the progress to its target value.
transition.job =
- launch { animatable.animateTo(targetProgress, animationSpec) }
+ launch { animatable.animateTo(targetProgress, animationSpec, initialVelocity) }
.apply {
invokeOnCompletion {
// Settle the state to Idle(target). Note that this will do nothing if this
// transition was replaced/interrupted by another one, and this also runs if
// this coroutine is cancelled, i.e. if [this] coroutine scope is cancelled.
- layoutState.finishTransition(transition, target)
+ layoutState.finishTransition(transition, targetScene)
}
}
@@ -185,6 +226,9 @@
override val progress: Float
get() = animatable.value
+ override val progressVelocity: Float
+ get() = animatable.velocity
+
override fun finish(): Job = job
}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
index f78ed2f..6758990 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
@@ -579,6 +579,18 @@
return offset / distance
}
+ override val progressVelocity: Float
+ get() {
+ val animatable = offsetAnimation?.animatable ?: return 0f
+ val distance = distance()
+ if (distance == DistanceUnspecified) {
+ return 0f
+ }
+
+ val velocityInDistanceUnit = animatable.velocity
+ return velocityInDistanceUnit / distance.absoluteValue
+ }
+
override val isInitiatedByUserInput = true
override var bouncingScene: SceneKey? = null
@@ -865,6 +877,7 @@
private val orientation: Orientation,
private val topOrLeftBehavior: NestedScrollBehavior,
private val bottomOrRightBehavior: NestedScrollBehavior,
+ private val isExternalOverscrollGesture: () -> Boolean,
) {
private val layoutState = layoutImpl.state
private val draggableHandler = layoutImpl.draggableHandler(orientation)
@@ -920,7 +933,8 @@
return PriorityNestedScrollConnection(
orientation = orientation,
canStartPreScroll = { offsetAvailable, offsetBeforeStart ->
- canChangeScene = offsetBeforeStart == 0f
+ canChangeScene =
+ if (isExternalOverscrollGesture()) false else offsetBeforeStart == 0f
val canInterceptSwipeTransition =
canChangeScene &&
@@ -950,7 +964,8 @@
else -> return@PriorityNestedScrollConnection false
}
- val isZeroOffset = offsetBeforeStart == 0f
+ val isZeroOffset =
+ if (isExternalOverscrollGesture()) false else offsetBeforeStart == 0f
val canStart =
when (behavior) {
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt
index ca64323..20742ee 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt
@@ -329,10 +329,9 @@
if (transition == null && previousTransition != null) {
// The transition was just finished.
- element.sceneStates.values.forEach { sceneState ->
- sceneState.offsetInterruptionDelta = Offset.Zero
- sceneState.scaleInterruptionDelta = Scale.Zero
- sceneState.alphaInterruptionDelta = 0f
+ element.sceneStates.values.forEach {
+ it.clearValuesBeforeInterruption()
+ it.clearInterruptionDeltas()
}
}
@@ -375,12 +374,22 @@
sceneState.scaleBeforeInterruption = lastScale
sceneState.alphaBeforeInterruption = lastAlpha
- sceneState.offsetInterruptionDelta = Offset.Zero
- sceneState.scaleInterruptionDelta = Scale.Zero
- sceneState.alphaInterruptionDelta = 0f
+ sceneState.clearInterruptionDeltas()
}
}
+private fun Element.SceneState.clearInterruptionDeltas() {
+ offsetInterruptionDelta = Offset.Zero
+ scaleInterruptionDelta = Scale.Zero
+ alphaInterruptionDelta = 0f
+}
+
+private fun Element.SceneState.clearValuesBeforeInterruption() {
+ offsetBeforeInterruption = Offset.Unspecified
+ scaleBeforeInterruption = Scale.Unspecified
+ alphaBeforeInterruption = Element.AlphaUnspecified
+}
+
/**
* Compute what [value] should be if we take the
* [interruption progress][TransitionState.Transition.interruptionProgress] of [transition] into
@@ -744,7 +753,11 @@
// No need to place the element in this scene if we don't want to draw it anyways.
if (!shouldPlaceElement(layoutImpl, scene, element, transition)) {
sceneState.lastOffset = Offset.Unspecified
- sceneState.offsetBeforeInterruption = Offset.Unspecified
+ sceneState.lastScale = Scale.Unspecified
+ sceneState.lastAlpha = Element.AlphaUnspecified
+
+ sceneState.clearValuesBeforeInterruption()
+ sceneState.clearInterruptionDeltas()
return
}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/InterruptionHandler.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/InterruptionHandler.kt
new file mode 100644
index 0000000..54c64fd
--- /dev/null
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/InterruptionHandler.kt
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.compose.animation.scene
+
+/**
+ * A handler to specify how a transition should be interrupted.
+ *
+ * @see DefaultInterruptionHandler
+ * @see SceneTransitionsBuilder.interruptionHandler
+ */
+interface InterruptionHandler {
+ /**
+ * This function is called when [interrupted] is interrupted: it is currently animating between
+ * [interrupted.fromScene] and [interrupted.toScene], and we will now animate to
+ * [newTargetScene].
+ *
+ * If this returns `null`, then the [default behavior][DefaultInterruptionHandler] will be used:
+ * we will animate from [interrupted.currentScene] and chaining will be enabled (see
+ * [InterruptionResult] for more information about chaining).
+ *
+ * @see InterruptionResult
+ */
+ fun onInterruption(
+ interrupted: TransitionState.Transition,
+ newTargetScene: SceneKey,
+ ): InterruptionResult?
+}
+
+/**
+ * The result of an interruption that specifies how we should handle a transition A => B now that we
+ * have to animate to C.
+ *
+ * For instance, if the interrupted transition was A => B and currentScene = B:
+ * - animateFrom = B && chain = true => there will be 2 transitions running in parallel, A => B and
+ * B => C.
+ * - animateFrom = A && chain = true => there will be 2 transitions running in parallel, B => A and
+ * A => C.
+ * - animateFrom = B && chain = false => there will be 1 transition running, B => C.
+ * - animateFrom = A && chain = false => there will be 1 transition running, A => C.
+ */
+class InterruptionResult(
+ /**
+ * The scene we should animate from when transitioning to C.
+ *
+ * Important: This **must** be either [TransitionState.Transition.fromScene] or
+ * [TransitionState.Transition.toScene] of the transition that was interrupted.
+ */
+ val animateFrom: SceneKey,
+
+ /**
+ * Whether chaining is enabled, i.e. if the new transition to C should run in parallel with the
+ * previous one(s) or if it should be the only remaining transition that is running.
+ */
+ val chain: Boolean = true,
+)
+
+/**
+ * The default interruption handler: we animate from [TransitionState.Transition.currentScene] and
+ * chaining is enabled.
+ */
+object DefaultInterruptionHandler : InterruptionHandler {
+ override fun onInterruption(
+ interrupted: TransitionState.Transition,
+ newTargetScene: SceneKey,
+ ): InterruptionResult {
+ return InterruptionResult(
+ animateFrom = interrupted.currentScene,
+ chain = true,
+ )
+ }
+}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MultiPointerDraggable.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MultiPointerDraggable.kt
index 05dd5cc..0fc0053 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MultiPointerDraggable.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MultiPointerDraggable.kt
@@ -17,8 +17,6 @@
package com.android.compose.animation.scene
import androidx.compose.foundation.gestures.Orientation
-import androidx.compose.foundation.gestures.awaitEachGesture
-import androidx.compose.foundation.gestures.awaitFirstDown
import androidx.compose.foundation.gestures.awaitHorizontalTouchSlopOrCancellation
import androidx.compose.foundation.gestures.awaitVerticalTouchSlopOrCancellation
import androidx.compose.foundation.gestures.horizontalDrag
@@ -26,12 +24,14 @@
import androidx.compose.runtime.Stable
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.input.pointer.AwaitPointerEventScope
import androidx.compose.ui.input.pointer.PointerEvent
import androidx.compose.ui.input.pointer.PointerEventPass
import androidx.compose.ui.input.pointer.PointerId
import androidx.compose.ui.input.pointer.PointerInputChange
import androidx.compose.ui.input.pointer.PointerInputScope
import androidx.compose.ui.input.pointer.SuspendingPointerInputModifierNode
+import androidx.compose.ui.input.pointer.changedToDownIgnoreConsumed
import androidx.compose.ui.input.pointer.positionChange
import androidx.compose.ui.input.pointer.util.VelocityTracker
import androidx.compose.ui.input.pointer.util.addPointerInputChange
@@ -45,8 +45,12 @@
import androidx.compose.ui.platform.LocalViewConfiguration
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.Velocity
+import androidx.compose.ui.util.fastAll
import androidx.compose.ui.util.fastForEach
+import kotlin.coroutines.cancellation.CancellationException
import kotlin.math.sign
+import kotlinx.coroutines.coroutineScope
+import kotlinx.coroutines.isActive
/**
* Make an element draggable in the given [orientation].
@@ -163,75 +167,95 @@
return
}
- detectDragGestures(
- orientation = orientation,
- startDragImmediately = startDragImmediately,
- onDragStart = { startedPosition, overSlop, pointersDown ->
- velocityTracker.resetTracking()
- onDragStarted(startedPosition, overSlop, pointersDown)
- },
- onDrag = { controller, change, amount ->
- velocityTracker.addPointerInputChange(change)
- controller.onDrag(amount)
- },
- onDragEnd = { controller ->
- val viewConfiguration = currentValueOf(LocalViewConfiguration)
- val maxVelocity = viewConfiguration.maximumFlingVelocity.let { Velocity(it, it) }
- val velocity = velocityTracker.calculateVelocity(maxVelocity)
- controller.onStop(
- velocity =
- when (orientation) {
- Orientation.Horizontal -> velocity.x
- Orientation.Vertical -> velocity.y
- },
- canChangeScene = true,
- )
- },
- onDragCancel = { controller ->
- controller.onStop(velocity = 0f, canChangeScene = true)
- },
- )
+ coroutineScope {
+ awaitPointerEventScope {
+ while (isActive) {
+ try {
+ detectDragGestures(
+ orientation = orientation,
+ startDragImmediately = startDragImmediately,
+ onDragStart = { startedPosition, overSlop, pointersDown ->
+ velocityTracker.resetTracking()
+ onDragStarted(startedPosition, overSlop, pointersDown)
+ },
+ onDrag = { controller, change, amount ->
+ velocityTracker.addPointerInputChange(change)
+ controller.onDrag(amount)
+ },
+ onDragEnd = { controller ->
+ val viewConfiguration = currentValueOf(LocalViewConfiguration)
+ val maxVelocity =
+ viewConfiguration.maximumFlingVelocity.let { Velocity(it, it) }
+ val velocity = velocityTracker.calculateVelocity(maxVelocity)
+ controller.onStop(
+ velocity =
+ when (orientation) {
+ Orientation.Horizontal -> velocity.x
+ Orientation.Vertical -> velocity.y
+ },
+ canChangeScene = true,
+ )
+ },
+ onDragCancel = { controller ->
+ controller.onStop(velocity = 0f, canChangeScene = true)
+ },
+ )
+ } catch (exception: CancellationException) {
+ // If the coroutine scope is active, we can just restart the drag cycle.
+ if (!isActive) {
+ throw exception
+ }
+ }
+ }
+ }
+ }
}
-}
-/**
- * Detect drag gestures in the given [orientation].
- *
- * This function is a mix of [androidx.compose.foundation.gestures.awaitDownAndSlop] and
- * [androidx.compose.foundation.gestures.detectVerticalDragGestures] to add support for:
- * 1) starting the gesture immediately without requiring a drag >= touch slope;
- * 2) passing the number of pointers down to [onDragStart].
- */
-private suspend fun PointerInputScope.detectDragGestures(
- orientation: Orientation,
- startDragImmediately: (startedPosition: Offset) -> Boolean,
- onDragStart: (startedPosition: Offset, overSlop: Float, pointersDown: Int) -> DragController,
- onDragEnd: (controller: DragController) -> Unit,
- onDragCancel: (controller: DragController) -> Unit,
- onDrag: (controller: DragController, change: PointerInputChange, dragAmount: Float) -> Unit,
-) {
- awaitEachGesture {
- val initialDown = awaitFirstDown(requireUnconsumed = false, pass = PointerEventPass.Initial)
+ /**
+ * Detect drag gestures in the given [orientation].
+ *
+ * This function is a mix of [androidx.compose.foundation.gestures.awaitDownAndSlop] and
+ * [androidx.compose.foundation.gestures.detectVerticalDragGestures] to add support for:
+ * 1) starting the gesture immediately without requiring a drag >= touch slope;
+ * 2) passing the number of pointers down to [onDragStart].
+ */
+ private suspend fun AwaitPointerEventScope.detectDragGestures(
+ orientation: Orientation,
+ startDragImmediately: (startedPosition: Offset) -> Boolean,
+ onDragStart:
+ (startedPosition: Offset, overSlop: Float, pointersDown: Int) -> DragController,
+ onDrag: (controller: DragController, change: PointerInputChange, dragAmount: Float) -> Unit,
+ onDragEnd: (controller: DragController) -> Unit,
+ onDragCancel: (controller: DragController) -> Unit
+ ) {
+ // Wait for a consumable event in [PointerEventPass.Main] pass
+ val consumablePointer = awaitConsumableEvent().changes.first()
+
var overSlop = 0f
val drag =
- if (startDragImmediately(initialDown.position)) {
- initialDown.consume()
- initialDown
+ if (startDragImmediately(consumablePointer.position)) {
+ consumablePointer.consume()
+ consumablePointer
} else {
- val down = awaitFirstDown(requireUnconsumed = false)
val onSlopReached = { change: PointerInputChange, over: Float ->
change.consume()
overSlop = over
}
- // TODO(b/291055080): Replace by await[Orientation]PointerSlopOrCancellation once
- // it is public.
+ // TODO(b/291055080): Replace by await[Orientation]PointerSlopOrCancellation once it
+ // is public.
val drag =
when (orientation) {
Orientation.Horizontal ->
- awaitHorizontalTouchSlopOrCancellation(down.id, onSlopReached)
+ awaitHorizontalTouchSlopOrCancellation(
+ consumablePointer.id,
+ onSlopReached
+ )
Orientation.Vertical ->
- awaitVerticalTouchSlopOrCancellation(down.id, onSlopReached)
+ awaitVerticalTouchSlopOrCancellation(
+ consumablePointer.id,
+ onSlopReached
+ )
}
// Make sure that overSlop is not 0f. This can happen when the user drags by exactly
@@ -240,16 +264,10 @@
// we intercept an ongoing swipe transition (i.e. startDragImmediately() returned
// true).
if (drag != null && overSlop == 0f) {
- val deltaOffset = drag.position - initialDown.position
- val delta =
- when (orientation) {
- Orientation.Horizontal -> deltaOffset.x
- Orientation.Vertical -> deltaOffset.y
- }
+ val delta = (drag.position - consumablePointer.position).toFloat()
check(delta != 0f) { "delta is equal to 0" }
overSlop = delta.sign
}
-
drag
}
@@ -272,12 +290,12 @@
when (orientation) {
Orientation.Horizontal ->
horizontalDrag(drag.id) {
- onDrag(controller, it, it.positionChange().x)
+ onDrag(controller, it, it.positionChange().toFloat())
it.consume()
}
Orientation.Vertical ->
verticalDrag(drag.id) {
- onDrag(controller, it, it.positionChange().y)
+ onDrag(controller, it, it.positionChange().toFloat())
it.consume()
}
}
@@ -293,4 +311,35 @@
}
}
}
+
+ private suspend fun AwaitPointerEventScope.awaitConsumableEvent(): PointerEvent {
+ fun canBeConsumed(changes: List<PointerInputChange>): Boolean {
+ // All pointers must be:
+ return changes.fastAll {
+ // A) recently pressed: even if the event has already been consumed, we can still
+ // use the recently added finger event to determine whether to initiate dragging the
+ // scene.
+ it.changedToDownIgnoreConsumed() ||
+ // B) unconsumed AND in a new position (on the current axis)
+ it.positionChange().toFloat() != 0f
+ }
+ }
+
+ var event: PointerEvent
+ do {
+ // To allow the descendants with the opportunity to consume the event, we wait for it in
+ // the Main pass.
+ event = awaitPointerEvent()
+ } while (!canBeConsumed(event.changes))
+
+ // We found a consumable event in the Main pass
+ return event
+ }
+
+ private fun Offset.toFloat(): Float {
+ return when (orientation) {
+ Orientation.Vertical -> y
+ Orientation.Horizontal -> x
+ }
+ }
}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/NestedScrollToScene.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/NestedScrollToScene.kt
index 5a2f85a..1fa6b3f7 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/NestedScrollToScene.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/NestedScrollToScene.kt
@@ -75,6 +75,7 @@
orientation: Orientation,
topOrLeftBehavior: NestedScrollBehavior,
bottomOrRightBehavior: NestedScrollBehavior,
+ isExternalOverscrollGesture: () -> Boolean,
) =
this then
NestedScrollToSceneElement(
@@ -82,6 +83,7 @@
orientation = orientation,
topOrLeftBehavior = topOrLeftBehavior,
bottomOrRightBehavior = bottomOrRightBehavior,
+ isExternalOverscrollGesture = isExternalOverscrollGesture,
)
private data class NestedScrollToSceneElement(
@@ -89,6 +91,7 @@
private val orientation: Orientation,
private val topOrLeftBehavior: NestedScrollBehavior,
private val bottomOrRightBehavior: NestedScrollBehavior,
+ private val isExternalOverscrollGesture: () -> Boolean,
) : ModifierNodeElement<NestedScrollToSceneNode>() {
override fun create() =
NestedScrollToSceneNode(
@@ -96,6 +99,7 @@
orientation = orientation,
topOrLeftBehavior = topOrLeftBehavior,
bottomOrRightBehavior = bottomOrRightBehavior,
+ isExternalOverscrollGesture = isExternalOverscrollGesture,
)
override fun update(node: NestedScrollToSceneNode) {
@@ -104,6 +108,7 @@
orientation = orientation,
topOrLeftBehavior = topOrLeftBehavior,
bottomOrRightBehavior = bottomOrRightBehavior,
+ isExternalOverscrollGesture = isExternalOverscrollGesture,
)
}
@@ -121,6 +126,7 @@
orientation: Orientation,
topOrLeftBehavior: NestedScrollBehavior,
bottomOrRightBehavior: NestedScrollBehavior,
+ isExternalOverscrollGesture: () -> Boolean,
) : DelegatingNode() {
private var priorityNestedScrollConnection: PriorityNestedScrollConnection =
scenePriorityNestedScrollConnection(
@@ -128,6 +134,7 @@
orientation = orientation,
topOrLeftBehavior = topOrLeftBehavior,
bottomOrRightBehavior = bottomOrRightBehavior,
+ isExternalOverscrollGesture = isExternalOverscrollGesture,
)
private var nestedScrollNode: DelegatableNode =
@@ -150,6 +157,7 @@
orientation: Orientation,
topOrLeftBehavior: NestedScrollBehavior,
bottomOrRightBehavior: NestedScrollBehavior,
+ isExternalOverscrollGesture: () -> Boolean,
) {
// Clean up the old nested scroll connection
priorityNestedScrollConnection.reset()
@@ -162,6 +170,7 @@
orientation = orientation,
topOrLeftBehavior = topOrLeftBehavior,
bottomOrRightBehavior = bottomOrRightBehavior,
+ isExternalOverscrollGesture = isExternalOverscrollGesture,
)
nestedScrollNode =
nestedScrollModifierNode(
@@ -177,11 +186,13 @@
orientation: Orientation,
topOrLeftBehavior: NestedScrollBehavior,
bottomOrRightBehavior: NestedScrollBehavior,
+ isExternalOverscrollGesture: () -> Boolean,
) =
NestedScrollHandlerImpl(
layoutImpl = layoutImpl,
orientation = orientation,
topOrLeftBehavior = topOrLeftBehavior,
bottomOrRightBehavior = bottomOrRightBehavior,
+ isExternalOverscrollGesture = isExternalOverscrollGesture,
)
.connection
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/ObservableTransitionState.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/ObservableTransitionState.kt
index 983cff8..d924d88 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/ObservableTransitionState.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/ObservableTransitionState.kt
@@ -19,6 +19,7 @@
import androidx.compose.runtime.snapshotFlow
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flowOf
/**
* A scene transition state.
@@ -33,14 +34,26 @@
* [ObservableTransitionState.Transition.toScene] will never be equal, while
* [TransitionState.Transition.fromScene] and [TransitionState.Transition.toScene] can be equal.
*/
-sealed class ObservableTransitionState {
+sealed interface ObservableTransitionState {
+ /**
+ * The current effective scene. If a new transition was triggered, it would start from this
+ * scene.
+ */
+ fun currentScene(): Flow<SceneKey> {
+ return when (this) {
+ is Idle -> flowOf(currentScene)
+ is Transition -> currentScene
+ }
+ }
+
/** No transition/animation is currently running. */
- data class Idle(val scene: SceneKey) : ObservableTransitionState()
+ data class Idle(val currentScene: SceneKey) : ObservableTransitionState
/** There is a transition animating between two scenes. */
- data class Transition(
+ class Transition(
val fromScene: SceneKey,
val toScene: SceneKey,
+ val currentScene: Flow<SceneKey>,
val progress: Flow<Float>,
/**
@@ -60,7 +73,7 @@
* the transition completes/settles.
*/
val isUserInputOngoing: Flow<Boolean>,
- ) : ObservableTransitionState()
+ ) : ObservableTransitionState
}
/**
@@ -76,6 +89,7 @@
ObservableTransitionState.Transition(
fromScene = state.fromScene,
toScene = state.toScene,
+ currentScene = snapshotFlow { state.currentScene },
progress = snapshotFlow { state.progress },
isInitiatedByUserInput = state.isInitiatedByUserInput,
isUserInputOngoing = snapshotFlow { state.isUserInputOngoing },
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Scene.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Scene.kt
index 339868c..6fef33c 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Scene.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Scene.kt
@@ -141,23 +141,27 @@
override fun Modifier.horizontalNestedScrollToScene(
leftBehavior: NestedScrollBehavior,
rightBehavior: NestedScrollBehavior,
+ isExternalOverscrollGesture: () -> Boolean,
): Modifier =
nestedScrollToScene(
layoutImpl = layoutImpl,
orientation = Orientation.Horizontal,
topOrLeftBehavior = leftBehavior,
bottomOrRightBehavior = rightBehavior,
+ isExternalOverscrollGesture = isExternalOverscrollGesture,
)
override fun Modifier.verticalNestedScrollToScene(
topBehavior: NestedScrollBehavior,
- bottomBehavior: NestedScrollBehavior
+ bottomBehavior: NestedScrollBehavior,
+ isExternalOverscrollGesture: () -> Boolean,
): Modifier =
nestedScrollToScene(
layoutImpl = layoutImpl,
orientation = Orientation.Vertical,
topOrLeftBehavior = topBehavior,
bottomOrRightBehavior = bottomBehavior,
+ isExternalOverscrollGesture = isExternalOverscrollGesture,
)
override fun Modifier.noResizeDuringTransitions(): Modifier {
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
index c7c874c..11e711a 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
@@ -250,6 +250,7 @@
fun Modifier.horizontalNestedScrollToScene(
leftBehavior: NestedScrollBehavior = NestedScrollBehavior.EdgeNoPreview,
rightBehavior: NestedScrollBehavior = NestedScrollBehavior.EdgeNoPreview,
+ isExternalOverscrollGesture: () -> Boolean = { false },
): Modifier
/**
@@ -262,6 +263,7 @@
fun Modifier.verticalNestedScrollToScene(
topBehavior: NestedScrollBehavior = NestedScrollBehavior.EdgeNoPreview,
bottomBehavior: NestedScrollBehavior = NestedScrollBehavior.EdgeNoPreview,
+ isExternalOverscrollGesture: () -> Boolean = { false },
): Modifier
/**
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutState.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutState.kt
index 5fda77a..4e3a032 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutState.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutState.kt
@@ -117,6 +117,9 @@
coroutineScope: CoroutineScope,
transitionKey: TransitionKey? = null,
): TransitionState.Transition?
+
+ /** Immediately snap to the given [scene]. */
+ fun snapToScene(scene: SceneKey)
}
/**
@@ -227,6 +230,9 @@
*/
abstract val progress: Float
+ /** The current velocity of [progress], in progress units. */
+ abstract val progressVelocity: Float
+
/** Whether the transition was triggered by user input rather than being programmatic. */
abstract val isInitiatedByUserInput: Boolean
@@ -422,13 +428,18 @@
}
/**
- * Start a new [transition], instantly interrupting any ongoing transition if there was one.
+ * Start a new [transition].
+ *
+ * If [chain] is `true`, then the transitions will simply be added to [currentTransitions] and
+ * will run in parallel to the current transitions. If [chain] is `false`, then the list of
+ * [currentTransitions] will be cleared and [transition] will be the only running transition.
*
* Important: you *must* call [finishTransition] once the transition is finished.
*/
internal fun startTransition(
transition: TransitionState.Transition,
transitionKey: TransitionKey?,
+ chain: Boolean = true,
) {
// Compute the [TransformationSpec] when the transition starts.
val fromScene = transition.fromScene
@@ -471,26 +482,10 @@
finishTransition(currentState, currentState.currentScene)
}
- // Check that we don't have too many concurrent transitions.
- if (transitionStates.size >= MAX_CONCURRENT_TRANSITIONS) {
- Log.wtf(
- TAG,
- buildString {
- appendLine("Potential leak detected in SceneTransitionLayoutState!")
- appendLine(
- " Some transition(s) never called STLState.finishTransition()."
- )
- appendLine(" Transitions (size=${transitionStates.size}):")
- transitionStates.fastForEach { state ->
- val transition = state as TransitionState.Transition
- val from = transition.fromScene
- val to = transition.toScene
- val indicator =
- if (finishedTransitions.contains(transition)) "x" else " "
- appendLine(" [$indicator] $from => $to ($transition)")
- }
- }
- )
+ val tooManyTransitions = transitionStates.size >= MAX_CONCURRENT_TRANSITIONS
+ val clearCurrentTransitions = !chain || tooManyTransitions
+ if (clearCurrentTransitions) {
+ if (tooManyTransitions) logTooManyTransitions()
// Force finish all transitions.
while (currentTransitions.isNotEmpty()) {
@@ -511,6 +506,24 @@
}
}
+ private fun logTooManyTransitions() {
+ Log.wtf(
+ TAG,
+ buildString {
+ appendLine("Potential leak detected in SceneTransitionLayoutState!")
+ appendLine(" Some transition(s) never called STLState.finishTransition().")
+ appendLine(" Transitions (size=${transitionStates.size}):")
+ transitionStates.fastForEach { state ->
+ val transition = state as TransitionState.Transition
+ val from = transition.fromScene
+ val to = transition.toScene
+ val indicator = if (finishedTransitions.contains(transition)) "x" else " "
+ appendLine(" [$indicator] $from => $to ($transition)")
+ }
+ }
+ )
+ }
+
private fun cancelActiveTransitionLinks() {
for ((link, linkedTransition) in activeTransitionLinks) {
link.target.finishTransition(linkedTransition, linkedTransition.currentScene)
@@ -735,6 +748,17 @@
override fun CoroutineScope.onChangeScene(scene: SceneKey) {
setTargetScene(scene, coroutineScope = this)
}
+
+ override fun snapToScene(scene: SceneKey) {
+ // Force finish all transitions.
+ while (currentTransitions.isNotEmpty()) {
+ val transition = transitionStates[0] as TransitionState.Transition
+ finishTransition(transition, transition.currentScene)
+ }
+
+ check(transitionStates.size == 1)
+ transitionStates[0] = TransitionState.Idle(scene)
+ }
}
private const val TAG = "SceneTransitionLayoutState"
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitions.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitions.kt
index b466143..0f6a1d2 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitions.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitions.kt
@@ -44,6 +44,7 @@
internal val defaultSwipeSpec: SpringSpec<Float>,
internal val transitionSpecs: List<TransitionSpecImpl>,
internal val overscrollSpecs: List<OverscrollSpecImpl>,
+ internal val interruptionHandler: InterruptionHandler,
) {
private val transitionCache =
mutableMapOf<
@@ -145,6 +146,7 @@
defaultSwipeSpec = DefaultSwipeSpec,
transitionSpecs = emptyList(),
overscrollSpecs = emptyList(),
+ interruptionHandler = DefaultInterruptionHandler,
)
}
}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDsl.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDsl.kt
index 6bc397e..a4682ff 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDsl.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDsl.kt
@@ -40,6 +40,12 @@
var defaultSwipeSpec: SpringSpec<Float>
/**
+ * The [InterruptionHandler] used when transitions are interrupted. Defaults to
+ * [DefaultInterruptionHandler].
+ */
+ var interruptionHandler: InterruptionHandler
+
+ /**
* Define the default animation to be played when transitioning [to] the specified scene, from
* any scene. For the animation specification to apply only when transitioning between two
* specific scenes, use [from] instead.
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDslImpl.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDslImpl.kt
index 1c9080f..802ab1f 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDslImpl.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDslImpl.kt
@@ -47,12 +47,14 @@
return SceneTransitions(
impl.defaultSwipeSpec,
impl.transitionSpecs,
- impl.transitionOverscrollSpecs
+ impl.transitionOverscrollSpecs,
+ impl.interruptionHandler,
)
}
private class SceneTransitionsBuilderImpl : SceneTransitionsBuilder {
override var defaultSwipeSpec: SpringSpec<Float> = SceneTransitions.DefaultSwipeSpec
+ override var interruptionHandler: InterruptionHandler = DefaultInterruptionHandler
val transitionSpecs = mutableListOf<TransitionSpecImpl>()
val transitionOverscrollSpecs = mutableListOf<OverscrollSpecImpl>()
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transition/link/LinkedTransition.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transition/link/LinkedTransition.kt
index 73393a1..79f126d 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transition/link/LinkedTransition.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transition/link/LinkedTransition.kt
@@ -45,5 +45,8 @@
override val progress: Float
get() = originalTransition.progress
+ override val progressVelocity: Float
+ get() = originalTransition.progressVelocity
+
override fun finish(): Job = originalTransition.finish()
}
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt
index 1fd1bf4..8625482 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt
@@ -32,12 +32,11 @@
import com.android.compose.animation.scene.TestScenes.SceneA
import com.android.compose.animation.scene.TestScenes.SceneB
import com.android.compose.animation.scene.TestScenes.SceneC
-import com.android.compose.animation.scene.TransitionState.Idle
import com.android.compose.animation.scene.TransitionState.Transition
+import com.android.compose.animation.scene.subjects.assertThat
import com.android.compose.test.MonotonicClockTestScope
import com.android.compose.test.runMonotonicClockTest
import com.google.common.truth.Truth.assertThat
-import com.google.common.truth.Truth.assertWithMessage
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.cancelAndJoin
import kotlinx.coroutines.launch
@@ -103,12 +102,16 @@
val draggableHandler = layoutImpl.draggableHandler(Orientation.Vertical)
val horizontalDraggableHandler = layoutImpl.draggableHandler(Orientation.Horizontal)
- fun nestedScrollConnection(nestedScrollBehavior: NestedScrollBehavior) =
+ fun nestedScrollConnection(
+ nestedScrollBehavior: NestedScrollBehavior,
+ isExternalOverscrollGesture: Boolean = false
+ ) =
NestedScrollHandlerImpl(
layoutImpl = layoutImpl,
orientation = draggableHandler.orientation,
topOrLeftBehavior = nestedScrollBehavior,
bottomOrRightBehavior = nestedScrollBehavior,
+ isExternalOverscrollGesture = { isExternalOverscrollGesture }
)
.connection
@@ -145,10 +148,8 @@
}
fun assertIdle(currentScene: SceneKey) {
- assertThat(transitionState).isInstanceOf(Idle::class.java)
- assertWithMessage("currentScene does not match")
- .that(transitionState.currentScene)
- .isEqualTo(currentScene)
+ assertThat(transitionState).isIdle()
+ assertThat(transitionState).hasCurrentScene(currentScene)
}
fun assertTransition(
@@ -158,34 +159,12 @@
progress: Float? = null,
isUserInputOngoing: Boolean? = null
) {
- assertThat(transitionState).isInstanceOf(Transition::class.java)
- val transition = transitionState as Transition
-
- if (currentScene != null)
- assertWithMessage("currentScene does not match")
- .that(transition.currentScene)
- .isEqualTo(currentScene)
-
- if (fromScene != null)
- assertWithMessage("fromScene does not match")
- .that(transition.fromScene)
- .isEqualTo(fromScene)
-
- if (toScene != null)
- assertWithMessage("toScene does not match")
- .that(transition.toScene)
- .isEqualTo(toScene)
-
- if (progress != null)
- assertWithMessage("progress does not match")
- .that(transition.progress)
- .isWithin(0f) // returns true when comparing 0.0f with -0.0f
- .of(progress)
-
- if (isUserInputOngoing != null)
- assertWithMessage("isUserInputOngoing does not match")
- .that(transition.isUserInputOngoing)
- .isEqualTo(isUserInputOngoing)
+ val transition = assertThat(transitionState).isTransition()
+ currentScene?.let { assertThat(transition).hasCurrentScene(it) }
+ fromScene?.let { assertThat(transition).hasFromScene(it) }
+ toScene?.let { assertThat(transition).hasToScene(it) }
+ progress?.let { assertThat(transition).hasProgress(it) }
+ isUserInputOngoing?.let { assertThat(transition).hasIsUserInputOngoing(it) }
}
fun onDragStarted(
@@ -801,6 +780,26 @@
}
@Test
+ fun flingAfterScrollStartedByExternalOverscrollGesture() = runGestureTest {
+ val nestedScroll =
+ nestedScrollConnection(
+ nestedScrollBehavior = EdgeWithPreview,
+ isExternalOverscrollGesture = true
+ )
+
+ // scroll not consumed in child
+ nestedScroll.scroll(
+ available = downOffset(fractionOfScreen = 0.1f),
+ )
+
+ // scroll offsetY10 is all available for parents
+ nestedScroll.scroll(available = downOffset(fractionOfScreen = 0.1f))
+ assertTransition(SceneA)
+
+ nestedScroll.preFling(available = Velocity(0f, velocityThreshold))
+ }
+
+ @Test
fun beforeNestedScrollStart_stop_shouldBeIgnored() = runGestureTest {
val nestedScroll = nestedScrollConnection(nestedScrollBehavior = EdgeWithPreview)
nestedScroll.preFling(available = Velocity(0f, velocityThreshold))
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt
index 92e1b2c..e19dc96 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt
@@ -20,7 +20,6 @@
import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.spring
import androidx.compose.animation.core.tween
-import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.gestures.rememberScrollableState
import androidx.compose.foundation.gestures.scrollable
@@ -43,7 +42,6 @@
import androidx.compose.runtime.setValue
import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Alignment
-import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.layout.approachLayout
@@ -64,6 +62,7 @@
import com.android.compose.animation.scene.TestScenes.SceneA
import com.android.compose.animation.scene.TestScenes.SceneB
import com.android.compose.animation.scene.TestScenes.SceneC
+import com.android.compose.animation.scene.subjects.assertThat
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
@@ -78,7 +77,6 @@
@get:Rule val rule = createComposeRule()
@Composable
- @OptIn(ExperimentalComposeUiApi::class)
private fun SceneScope.Element(
key: ElementKey,
size: Dp,
@@ -496,7 +494,6 @@
}
@Test
- @OptIn(ExperimentalFoundationApi::class)
fun elementModifierNodeIsRecycledInLazyLayouts() = runTest {
val nPages = 2
val pagerState = PagerState(currentPage = 0) { nPages }
@@ -654,8 +651,7 @@
}
}
- assertThat(state.currentTransition).isNull()
- assertThat(state.currentTransition?.currentOverscrollSpec).isNull()
+ assertThat(state.transitionState).isIdle()
// Swipe by half of verticalSwipeDistance.
rule.onRoot().performTouchInput {
@@ -691,9 +687,9 @@
val fooElement = rule.onNodeWithTag(TestElements.Foo.testTag, useUnmergedTree = true)
fooElement.assertTopPositionInRootIsEqualTo(0.dp)
- val transition = state.currentTransition
+ val transition = assertThat(state.transitionState).isTransition()
assertThat(transition).isNotNull()
- assertThat(transition!!.progress).isEqualTo(0.5f)
+ assertThat(transition).hasProgress(0.5f)
assertThat(animatedFloat).isEqualTo(50f)
rule.onRoot().performTouchInput {
@@ -702,8 +698,8 @@
}
// Scroll 150% (Scene B overscroll by 50%)
- assertThat(transition.progress).isEqualTo(1.5f)
- assertThat(state.currentTransition?.currentOverscrollSpec).isNotNull()
+ assertThat(transition).hasProgress(1.5f)
+ assertThat(transition).hasOverscrollSpec()
fooElement.assertTopPositionInRootIsEqualTo(overscrollTranslateY * 0.5f)
// animatedFloat cannot overflow (canOverflow = false)
assertThat(animatedFloat).isEqualTo(100f)
@@ -714,8 +710,8 @@
}
// Scroll 250% (Scene B overscroll by 150%)
- assertThat(transition.progress).isEqualTo(2.5f)
- assertThat(state.currentTransition?.currentOverscrollSpec).isNotNull()
+ assertThat(transition).hasProgress(2.5f)
+ assertThat(transition).hasOverscrollSpec()
fooElement.assertTopPositionInRootIsEqualTo(overscrollTranslateY * 1.5f)
assertThat(animatedFloat).isEqualTo(100f)
}
@@ -766,8 +762,7 @@
}
}
- assertThat(state.currentTransition).isNull()
- assertThat(state.currentTransition?.currentOverscrollSpec).isNull()
+ assertThat(state.transitionState).isIdle()
val fooElement = rule.onNodeWithTag(TestElements.Foo.testTag, useUnmergedTree = true)
fooElement.assertTopPositionInRootIsEqualTo(0.dp)
@@ -779,10 +774,9 @@
moveBy(Offset(0f, touchSlop + layoutHeight.toPx() * 0.5f), delayMillis = 1_000)
}
- val transition = state.currentTransition
- assertThat(state.currentTransition?.currentOverscrollSpec).isNotNull()
- assertThat(transition).isNotNull()
- assertThat(transition!!.progress).isEqualTo(-0.5f)
+ val transition = assertThat(state.transitionState).isTransition()
+ assertThat(transition).hasOverscrollSpec()
+ assertThat(transition).hasProgress(-0.5f)
fooElement.assertTopPositionInRootIsEqualTo(overscrollTranslateY * 0.5f)
rule.onRoot().performTouchInput {
@@ -791,8 +785,8 @@
}
// Scroll 150% (Scene B overscroll by 50%)
- assertThat(transition.progress).isEqualTo(-1.5f)
- assertThat(state.currentTransition?.currentOverscrollSpec).isNotNull()
+ assertThat(transition).hasProgress(-1.5f)
+ assertThat(transition).hasOverscrollSpec()
fooElement.assertTopPositionInRootIsEqualTo(overscrollTranslateY * 1.5f)
}
@@ -825,13 +819,12 @@
moveBy(Offset(0f, layoutHeight.toPx() * 0.5f), delayMillis = 1_000)
}
- val transition = state.currentTransition
- assertThat(transition).isNotNull()
+ val transition = assertThat(state.transitionState).isTransition()
assertThat(animatedFloat).isEqualTo(100f)
// Scroll 150% (100% scroll + 50% overscroll)
- assertThat(transition!!.progress).isEqualTo(1.5f)
- assertThat(state.currentTransition?.currentOverscrollSpec).isNotNull()
+ assertThat(transition).hasProgress(1.5f)
+ assertThat(transition).hasOverscrollSpec()
fooElement.assertTopPositionInRootIsEqualTo(layoutHeight * 0.5f)
assertThat(animatedFloat).isEqualTo(100f)
@@ -841,8 +834,8 @@
}
// Scroll 250% (100% scroll + 150% overscroll)
- assertThat(transition.progress).isEqualTo(2.5f)
- assertThat(state.currentTransition?.currentOverscrollSpec).isNotNull()
+ assertThat(transition).hasProgress(2.5f)
+ assertThat(transition).hasOverscrollSpec()
fooElement.assertTopPositionInRootIsEqualTo(layoutHeight * 1.5f)
assertThat(animatedFloat).isEqualTo(100f)
}
@@ -882,13 +875,11 @@
moveBy(Offset(0f, layoutHeight.toPx() * 0.5f), delayMillis = 1_000)
}
- val transition = state.currentTransition
- assertThat(transition).isNotNull()
- transition as TransitionState.HasOverscrollProperties
+ val transition = assertThat(state.transitionState).isTransition()
// Scroll 150% (100% scroll + 50% overscroll)
- assertThat(transition.progress).isEqualTo(1.5f)
- assertThat(state.currentTransition?.currentOverscrollSpec).isNotNull()
+ assertThat(transition).hasProgress(1.5f)
+ assertThat(transition).hasOverscrollSpec()
fooElement.assertTopPositionInRootIsEqualTo(layoutHeight * (transition.progress - 1f))
assertThat(animatedFloat).isEqualTo(100f)
@@ -900,8 +891,8 @@
rule.waitUntil(timeoutMillis = 10_000) { transition.progress < 1f }
assertThat(transition.progress).isLessThan(1f)
- assertThat(state.currentTransition?.currentOverscrollSpec).isNotNull()
- assertThat(transition.bouncingScene).isEqualTo(transition.toScene)
+ assertThat(transition).hasOverscrollSpec()
+ assertThat(transition).hasBouncingScene(transition.toScene)
assertThat(animatedFloat).isEqualTo(100f)
}
@@ -980,13 +971,13 @@
val transitions = state.currentTransitions
assertThat(transitions).hasSize(2)
- assertThat(transitions[0].fromScene).isEqualTo(SceneA)
- assertThat(transitions[0].toScene).isEqualTo(SceneB)
- assertThat(transitions[0].progress).isEqualTo(0f)
+ assertThat(transitions[0]).hasFromScene(SceneA)
+ assertThat(transitions[0]).hasToScene(SceneB)
+ assertThat(transitions[0]).hasProgress(0f)
- assertThat(transitions[1].fromScene).isEqualTo(SceneB)
- assertThat(transitions[1].toScene).isEqualTo(SceneC)
- assertThat(transitions[1].progress).isEqualTo(0f)
+ assertThat(transitions[1]).hasFromScene(SceneB)
+ assertThat(transitions[1]).hasToScene(SceneC)
+ assertThat(transitions[1]).hasProgress(0f)
// First frame: both are at x = 0dp. For the whole transition, Foo is at y = 0dp and Bar is
// at y = layoutSize - elementSoze = 100dp.
@@ -1049,24 +1040,30 @@
Box(modifier.element(TestElements.Foo).size(fooSize))
}
+ lateinit var layoutImpl: SceneTransitionLayoutImpl
rule.setContent {
- SceneTransitionLayout(state, Modifier.size(layoutSize)) {
+ SceneTransitionLayoutForTesting(
+ state,
+ Modifier.size(layoutSize),
+ onLayoutImpl = { layoutImpl = it },
+ ) {
// In scene A, Foo is aligned at the TopStart.
scene(SceneA) {
Box(Modifier.fillMaxSize()) { Foo(Modifier.align(Alignment.TopStart)) }
}
+ // In scene C, Foo is aligned at the BottomEnd, so it moves vertically when coming
+ // from B. We put it before (below) scene B so that we can check that interruptions
+ // values and deltas are properly cleared once all transitions are done.
+ scene(SceneC) {
+ Box(Modifier.fillMaxSize()) { Foo(Modifier.align(Alignment.BottomEnd)) }
+ }
+
// In scene B, Foo is aligned at the TopEnd, so it moves horizontally when coming
// from A.
scene(SceneB) {
Box(Modifier.fillMaxSize()) { Foo(Modifier.align(Alignment.TopEnd)) }
}
-
- // In scene C, Foo is aligned at the BottomEnd, so it moves vertically when coming
- // from B.
- scene(SceneC) {
- Box(Modifier.fillMaxSize()) { Foo(Modifier.align(Alignment.BottomEnd)) }
- }
}
}
@@ -1115,7 +1112,7 @@
// Interruption progress is at 100% and bToC is at 0%, so Foo should be at the same offset
// as right before the interruption.
rule
- .onNode(isElement(TestElements.Foo, SceneC))
+ .onNode(isElement(TestElements.Foo, SceneB))
.assertPositionInRootIsEqualTo(offsetInAToB.x, offsetInAToB.y)
// Move the transition forward at 30% and set the interruption progress to 50%.
@@ -1130,7 +1127,7 @@
)
rule.waitForIdle()
rule
- .onNode(isElement(TestElements.Foo, SceneC))
+ .onNode(isElement(TestElements.Foo, SceneB))
.assertPositionInRootIsEqualTo(
offsetInBToCWithInterruption.x,
offsetInBToCWithInterruption.y,
@@ -1140,7 +1137,24 @@
bToCProgress = 1f
interruptionProgress = 0f
rule
- .onNode(isElement(TestElements.Foo, SceneC))
+ .onNode(isElement(TestElements.Foo, SceneB))
.assertPositionInRootIsEqualTo(offsetInC.x, offsetInC.y)
+
+ // Manually finish the transition.
+ state.finishTransition(aToB, SceneB)
+ state.finishTransition(bToC, SceneC)
+ rule.waitForIdle()
+ assertThat(state.transitionState).isIdle()
+
+ // The interruption values should be unspecified and deltas should be set to zero.
+ val foo = layoutImpl.elements.getValue(TestElements.Foo)
+ assertThat(foo.sceneStates.keys).containsExactly(SceneC)
+ val stateInC = foo.sceneStates.getValue(SceneC)
+ assertThat(stateInC.offsetBeforeInterruption).isEqualTo(Offset.Unspecified)
+ assertThat(stateInC.scaleBeforeInterruption).isEqualTo(Scale.Unspecified)
+ assertThat(stateInC.alphaBeforeInterruption).isEqualTo(Element.AlphaUnspecified)
+ assertThat(stateInC.offsetInterruptionDelta).isEqualTo(Offset.Zero)
+ assertThat(stateInC.scaleInterruptionDelta).isEqualTo(Scale.Zero)
+ assertThat(stateInC.alphaInterruptionDelta).isEqualTo(0f)
}
}
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/InterruptionHandlerTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/InterruptionHandlerTest.kt
new file mode 100644
index 0000000..85d4165
--- /dev/null
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/InterruptionHandlerTest.kt
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.compose.animation.scene
+
+import androidx.compose.animation.core.tween
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.compose.animation.scene.TestScenes.SceneA
+import com.android.compose.animation.scene.TestScenes.SceneB
+import com.android.compose.animation.scene.TestScenes.SceneC
+import com.android.compose.animation.scene.subjects.assertThat
+import com.android.compose.test.runMonotonicClockTest
+import com.google.common.truth.Correspondence
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.launch
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class InterruptionHandlerTest {
+ @get:Rule val rule = createComposeRule()
+
+ @Test
+ fun default() = runMonotonicClockTest {
+ val state =
+ MutableSceneTransitionLayoutState(
+ SceneA,
+ transitions { /* default interruption handler */},
+ )
+
+ state.setTargetScene(SceneB, coroutineScope = this)
+ state.setTargetScene(SceneC, coroutineScope = this)
+
+ assertThat(state.currentTransitions)
+ .comparingElementsUsing(FromToCurrentTriple)
+ .containsExactly(
+ // A to B.
+ Triple(SceneA, SceneB, SceneB),
+
+ // B to C.
+ Triple(SceneB, SceneC, SceneC),
+ )
+ .inOrder()
+ }
+
+ @Test
+ fun chainingDisabled() = runMonotonicClockTest {
+ val state =
+ MutableSceneTransitionLayoutState(
+ SceneA,
+ transitions {
+ // Handler that animates from currentScene (default) but disables chaining.
+ interruptionHandler =
+ object : InterruptionHandler {
+ override fun onInterruption(
+ interrupted: TransitionState.Transition,
+ newTargetScene: SceneKey
+ ): InterruptionResult {
+ return InterruptionResult(
+ animateFrom = interrupted.currentScene,
+ chain = false,
+ )
+ }
+ }
+ },
+ )
+
+ state.setTargetScene(SceneB, coroutineScope = this)
+ state.setTargetScene(SceneC, coroutineScope = this)
+
+ assertThat(state.currentTransitions)
+ .comparingElementsUsing(FromToCurrentTriple)
+ .containsExactly(
+ // B to C.
+ Triple(SceneB, SceneC, SceneC),
+ )
+ .inOrder()
+ }
+
+ @Test
+ fun animateFromOtherScene() = runMonotonicClockTest {
+ val duration = 500
+ val state =
+ MutableSceneTransitionLayoutState(
+ SceneA,
+ transitions {
+ // Handler that animates from the scene that is not currentScene.
+ interruptionHandler =
+ object : InterruptionHandler {
+ override fun onInterruption(
+ interrupted: TransitionState.Transition,
+ newTargetScene: SceneKey
+ ): InterruptionResult {
+ return InterruptionResult(
+ animateFrom =
+ if (interrupted.currentScene == interrupted.toScene) {
+ interrupted.fromScene
+ } else {
+ interrupted.toScene
+ }
+ )
+ }
+ }
+
+ from(SceneA, to = SceneB) { spec = tween(duration) }
+ },
+ )
+
+ // Animate to B and advance the transition a little bit so that progress > visibility
+ // threshold and that reversing from B back to A won't immediately snap to A.
+ state.setTargetScene(SceneB, coroutineScope = this)
+ testScheduler.advanceTimeBy(duration / 2L)
+
+ state.setTargetScene(SceneC, coroutineScope = this)
+
+ assertThat(state.currentTransitions)
+ .comparingElementsUsing(FromToCurrentTriple)
+ .containsExactly(
+ // Initial transition A to B. This transition will never be consumed by anyone given
+ // that it has the same (from, to) pair as the next transition.
+ Triple(SceneA, SceneB, SceneB),
+
+ // Initial transition reversed, B back to A.
+ Triple(SceneA, SceneB, SceneA),
+
+ // A to C.
+ Triple(SceneA, SceneC, SceneC),
+ )
+ .inOrder()
+ }
+
+ @Test
+ fun animateToFromScene() = runMonotonicClockTest {
+ val state = MutableSceneTransitionLayoutStateImpl(SceneA, transitions {})
+
+ // Fake a transition from A to B that has a non 0 velocity.
+ val progressVelocity = 1f
+ val aToB =
+ transition(
+ from = SceneA,
+ to = SceneB,
+ current = { SceneB },
+ // Progress must be > visibility threshold otherwise we will directly snap to A.
+ progress = { 0.5f },
+ progressVelocity = { progressVelocity },
+ onFinish = { launch {} },
+ )
+ state.startTransition(aToB, transitionKey = null)
+
+ // Animate back to A. The previous transition is reversed, i.e. it has the same (from, to)
+ // pair, and its velocity is used when animating the progress back to 0.
+ val bToA = checkNotNull(state.setTargetScene(SceneA, coroutineScope = this))
+ testScheduler.runCurrent()
+ assertThat(bToA).hasFromScene(SceneA)
+ assertThat(bToA).hasToScene(SceneB)
+ assertThat(bToA).hasCurrentScene(SceneA)
+ assertThat(bToA).hasProgressVelocity(progressVelocity)
+ }
+
+ @Test
+ fun animateToToScene() = runMonotonicClockTest {
+ val state = MutableSceneTransitionLayoutStateImpl(SceneA, transitions {})
+
+ // Fake a transition from A to B with current scene = A that has a non 0 velocity.
+ val progressVelocity = -1f
+ val aToB =
+ transition(
+ from = SceneA,
+ to = SceneB,
+ current = { SceneA },
+ progressVelocity = { progressVelocity },
+ onFinish = { launch {} },
+ )
+ state.startTransition(aToB, transitionKey = null)
+
+ // Animate to B. The previous transition is reversed, i.e. it has the same (from, to) pair,
+ // and its velocity is used when animating the progress to 1.
+ val bToA = checkNotNull(state.setTargetScene(SceneB, coroutineScope = this))
+ testScheduler.runCurrent()
+ assertThat(bToA).hasFromScene(SceneA)
+ assertThat(bToA).hasToScene(SceneB)
+ assertThat(bToA).hasCurrentScene(SceneB)
+ assertThat(bToA).hasProgressVelocity(progressVelocity)
+ }
+
+ companion object {
+ val FromToCurrentTriple =
+ Correspondence.transforming(
+ { transition: TransitionState.Transition? ->
+ Triple(transition?.fromScene, transition?.toScene, transition?.currentScene)
+ },
+ "(from, to, current) triple"
+ )
+ }
+}
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MovableElementTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MovableElementTest.kt
index 224ffe2..9523896 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MovableElementTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MovableElementTest.kt
@@ -43,6 +43,7 @@
import androidx.compose.ui.test.performClick
import androidx.compose.ui.unit.dp
import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.compose.animation.scene.subjects.assertThat
import com.android.compose.test.assertSizeIsEqualTo
import com.google.common.truth.Truth.assertThat
import org.junit.Rule
@@ -157,8 +158,8 @@
fromSceneZIndex: Float,
toSceneZIndex: Float
): SceneKey {
- assertThat(transition.fromScene).isEqualTo(TestScenes.SceneA)
- assertThat(transition.toScene).isEqualTo(TestScenes.SceneB)
+ assertThat(transition).hasFromScene(TestScenes.SceneA)
+ assertThat(transition).hasToScene(TestScenes.SceneB)
assertThat(fromSceneZIndex).isEqualTo(0)
assertThat(toSceneZIndex).isEqualTo(1)
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MultiPointerDraggableTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MultiPointerDraggableTest.kt
index d8cf1c1..aa6d113 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MultiPointerDraggableTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MultiPointerDraggableTest.kt
@@ -17,7 +17,10 @@
package com.android.compose.animation.scene
import androidx.compose.foundation.gestures.Orientation
+import androidx.compose.foundation.gestures.rememberScrollableState
+import androidx.compose.foundation.gestures.scrollable
import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
@@ -25,6 +28,9 @@
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
+import androidx.compose.ui.input.pointer.AwaitPointerEventScope
+import androidx.compose.ui.input.pointer.PointerEventPass
+import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalViewConfiguration
import androidx.compose.ui.test.junit4.createComposeRule
@@ -32,6 +38,8 @@
import androidx.compose.ui.test.performTouchInput
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.coroutineScope
+import kotlinx.coroutines.isActive
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -110,4 +118,232 @@
assertThat(dragged).isTrue()
assertThat(stopped).isTrue()
}
+
+ @Test
+ fun handleDisappearingScrollableDuringAGesture() {
+ val size = 200f
+ val middle = Offset(size / 2f, size / 2f)
+
+ var started = false
+ var dragged = false
+ var stopped = false
+ var consumedByScroll = false
+ var hasScrollable by mutableStateOf(true)
+
+ var touchSlop = 0f
+ rule.setContent {
+ touchSlop = LocalViewConfiguration.current.touchSlop
+ Box(
+ Modifier.size(with(LocalDensity.current) { Size(size, size).toDpSize() })
+ .multiPointerDraggable(
+ orientation = Orientation.Vertical,
+ enabled = { true },
+ startDragImmediately = { false },
+ onDragStarted = { _, _, _ ->
+ started = true
+ object : DragController {
+ override fun onDrag(delta: Float) {
+ dragged = true
+ }
+
+ override fun onStop(velocity: Float, canChangeScene: Boolean) {
+ stopped = true
+ }
+ }
+ },
+ )
+ ) {
+ if (hasScrollable) {
+ Box(
+ Modifier.scrollable(
+ // Consume all the vertical scroll gestures
+ rememberScrollableState(
+ consumeScrollDelta = {
+ consumedByScroll = true
+ it
+ }
+ ),
+ Orientation.Vertical
+ )
+ .fillMaxSize()
+ )
+ }
+ }
+ }
+
+ fun startDraggingDown() {
+ rule.onRoot().performTouchInput {
+ down(middle)
+ moveBy(Offset(0f, touchSlop))
+ }
+ }
+
+ fun continueDraggingDown() {
+ rule.onRoot().performTouchInput { moveBy(Offset(0f, touchSlop)) }
+ }
+
+ fun releaseFinger() {
+ rule.onRoot().performTouchInput { up() }
+ }
+
+ // Swipe down. This should intercepted by the scrollable modifier.
+ startDraggingDown()
+ assertThat(consumedByScroll).isTrue()
+ assertThat(started).isFalse()
+ assertThat(dragged).isFalse()
+ assertThat(stopped).isFalse()
+
+ // Reset the scroll state for the test
+ consumedByScroll = false
+
+ // Suddenly remove the scrollable container
+ hasScrollable = false
+ rule.waitForIdle()
+
+ // Swipe down. This will be intercepted by multiPointerDraggable, it will wait touchSlop
+ // before consuming it.
+ continueDraggingDown()
+ assertThat(consumedByScroll).isFalse()
+ assertThat(started).isFalse()
+ assertThat(dragged).isFalse()
+ assertThat(stopped).isFalse()
+
+ // Swipe down. This should both call onDragStarted() and onDragDelta().
+ continueDraggingDown()
+ assertThat(consumedByScroll).isFalse()
+ assertThat(started).isTrue()
+ assertThat(dragged).isTrue()
+ assertThat(stopped).isFalse()
+
+ rule.waitForIdle()
+ releaseFinger()
+ assertThat(stopped).isTrue()
+ }
+
+ @Test
+ fun multiPointerWaitAConsumableEventInMainPass() {
+ val size = 200f
+ val middle = Offset(size / 2f, size / 2f)
+
+ var started = false
+ var dragged = false
+ var stopped = false
+
+ var childConsumesOnPass: PointerEventPass? = null
+
+ suspend fun AwaitPointerEventScope.childPointerInputScope() {
+ awaitPointerEvent(PointerEventPass.Initial).also { initial ->
+ // Check unconsumed: it should be always true
+ assertThat(initial.changes.any { it.isConsumed }).isFalse()
+
+ if (childConsumesOnPass == PointerEventPass.Initial) {
+ initial.changes.first().consume()
+ }
+ }
+
+ awaitPointerEvent(PointerEventPass.Main).also { main ->
+ // Check unconsumed
+ if (childConsumesOnPass != PointerEventPass.Initial) {
+ assertThat(main.changes.any { it.isConsumed }).isFalse()
+ }
+
+ if (childConsumesOnPass == PointerEventPass.Main) {
+ main.changes.first().consume()
+ }
+ }
+ }
+
+ var touchSlop = 0f
+ rule.setContent {
+ touchSlop = LocalViewConfiguration.current.touchSlop
+ Box(
+ Modifier.size(with(LocalDensity.current) { Size(size, size).toDpSize() })
+ .multiPointerDraggable(
+ orientation = Orientation.Vertical,
+ enabled = { true },
+ startDragImmediately = { false },
+ onDragStarted = { _, _, _ ->
+ started = true
+ object : DragController {
+ override fun onDrag(delta: Float) {
+ dragged = true
+ }
+
+ override fun onStop(velocity: Float, canChangeScene: Boolean) {
+ stopped = true
+ }
+ }
+ },
+ )
+ ) {
+ Box(
+ Modifier.pointerInput(Unit) {
+ coroutineScope {
+ awaitPointerEventScope {
+ while (isActive) {
+ childPointerInputScope()
+ }
+ }
+ }
+ }
+ .fillMaxSize()
+ )
+ }
+ }
+
+ fun startDraggingDown() {
+ rule.onRoot().performTouchInput {
+ down(middle)
+ moveBy(Offset(0f, touchSlop))
+ }
+ }
+
+ fun continueDraggingDown() {
+ rule.onRoot().performTouchInput { moveBy(Offset(0f, touchSlop)) }
+ }
+
+ childConsumesOnPass = PointerEventPass.Initial
+
+ startDraggingDown()
+ assertThat(started).isFalse()
+ assertThat(dragged).isFalse()
+ assertThat(stopped).isFalse()
+
+ continueDraggingDown()
+ assertThat(started).isFalse()
+ assertThat(dragged).isFalse()
+ assertThat(stopped).isFalse()
+
+ childConsumesOnPass = PointerEventPass.Main
+
+ continueDraggingDown()
+ assertThat(started).isFalse()
+ assertThat(dragged).isFalse()
+ assertThat(stopped).isFalse()
+
+ continueDraggingDown()
+ assertThat(started).isFalse()
+ assertThat(dragged).isFalse()
+ assertThat(stopped).isFalse()
+
+ childConsumesOnPass = null
+
+ // Swipe down. This will be intercepted by multiPointerDraggable, it will wait touchSlop
+ // before consuming it.
+ continueDraggingDown()
+ assertThat(started).isFalse()
+ assertThat(dragged).isFalse()
+ assertThat(stopped).isFalse()
+
+ // Swipe down. This should both call onDragStarted() and onDragDelta().
+ continueDraggingDown()
+ assertThat(started).isTrue()
+ assertThat(dragged).isTrue()
+ assertThat(stopped).isFalse()
+
+ childConsumesOnPass = PointerEventPass.Main
+
+ continueDraggingDown()
+ assertThat(stopped).isTrue()
+ }
}
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ObservableTransitionStateTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ObservableTransitionStateTest.kt
index 0f9b024..2a75e13 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ObservableTransitionStateTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ObservableTransitionStateTest.kt
@@ -16,10 +16,18 @@
package com.android.compose.animation.scene
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.setValue
+import androidx.compose.runtime.snapshots.Snapshot
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.compose.animation.scene.TestScenes.SceneA
+import com.android.compose.animation.scene.TestScenes.SceneB
import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.launch
+import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Rule
@@ -55,8 +63,8 @@
}
rule.testTransition(
- from = TestScenes.SceneA,
- to = TestScenes.SceneB,
+ from = SceneA,
+ to = SceneB,
transitionLayout = { currentScene, onChangeScene ->
state =
updateSceneTransitionLayoutState(
@@ -66,34 +74,90 @@
)
SceneTransitionLayout(state = state) {
- scene(TestScenes.SceneA) {}
- scene(TestScenes.SceneB) {}
+ scene(SceneA) {}
+ scene(SceneB) {}
}
}
) {
before {
- assertThat(observableState())
- .isEqualTo(ObservableTransitionState.Idle(TestScenes.SceneA))
+ assertThat(observableState()).isEqualTo(ObservableTransitionState.Idle(SceneA))
}
at(0) {
val state = observableState()
assertThat(state).isInstanceOf(ObservableTransitionState.Transition::class.java)
assertThat((state as ObservableTransitionState.Transition).fromScene)
- .isEqualTo(TestScenes.SceneA)
- assertThat(state.toScene).isEqualTo(TestScenes.SceneB)
+ .isEqualTo(SceneA)
+ assertThat(state.toScene).isEqualTo(SceneB)
assertThat(state.progress()).isEqualTo(0f)
}
at(TestTransitionDuration / 2) {
val state = observableState()
assertThat((state as ObservableTransitionState.Transition).fromScene)
- .isEqualTo(TestScenes.SceneA)
- assertThat(state.toScene).isEqualTo(TestScenes.SceneB)
+ .isEqualTo(SceneA)
+ assertThat(state.toScene).isEqualTo(SceneB)
assertThat(state.progress()).isEqualTo(0.5f)
}
after {
- assertThat(observableState())
- .isEqualTo(ObservableTransitionState.Idle(TestScenes.SceneB))
+ assertThat(observableState()).isEqualTo(ObservableTransitionState.Idle(SceneB))
}
}
}
+
+ @Test
+ fun observableCurrentScene() = runTestWithSnapshots {
+ val state =
+ MutableSceneTransitionLayoutStateImpl(
+ initialScene = SceneA,
+ transitions = transitions {},
+ )
+ val observableCurrentScene =
+ state.observableTransitionState().flatMapLatest { it.currentScene() }
+
+ // Collect observableCurrentScene into currentScene (unfortunately we can't use
+ // collectValues in this test target).
+ val currentScene =
+ object {
+ private var _value: SceneKey? = null
+ val value: SceneKey
+ get() {
+ runCurrent()
+ return _value ?: error("observableCurrentScene has no value")
+ }
+
+ init {
+ backgroundScope.launch { observableCurrentScene.collect { _value = it } }
+ }
+ }
+
+ assertThat(currentScene.value).isEqualTo(SceneA)
+
+ // Start a transition to Scene B.
+ var transitionCurrentScene by mutableStateOf(SceneA)
+ val transition =
+ transition(from = SceneA, to = SceneB, current = { transitionCurrentScene })
+ state.startTransition(transition, transitionKey = null)
+ assertThat(currentScene.value).isEqualTo(SceneA)
+
+ // Change the transition current scene.
+ transitionCurrentScene = SceneB
+ assertThat(currentScene.value).isEqualTo(SceneB)
+
+ transitionCurrentScene = SceneA
+ assertThat(currentScene.value).isEqualTo(SceneA)
+ }
+
+ // See http://shortn/_hj4Mhikmos for inspiration.
+ private fun runTestWithSnapshots(testBody: suspend TestScope.() -> Unit) {
+ val globalWriteObserverHandle =
+ Snapshot.registerGlobalWriteObserver {
+ // This is normally done by the compose runtime.
+ Snapshot.sendApplyNotifications()
+ }
+
+ try {
+ runTest(testBody = testBody)
+ } finally {
+ globalWriteObserverHandle.dispose()
+ }
+ }
}
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutStateTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutStateTest.kt
index 93e94f8..d2c8bd6 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutStateTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutStateTest.kt
@@ -25,6 +25,7 @@
import com.android.compose.animation.scene.TestScenes.SceneB
import com.android.compose.animation.scene.TestScenes.SceneC
import com.android.compose.animation.scene.TestScenes.SceneD
+import com.android.compose.animation.scene.subjects.assertThat
import com.android.compose.animation.scene.transition.link.StateLink
import com.android.compose.test.runMonotonicClockTest
import com.google.common.truth.Truth.assertThat
@@ -322,8 +323,8 @@
// Go back to A.
state.setTargetScene(SceneA, coroutineScope = this)
testScheduler.advanceUntilIdle()
- assertThat(state.currentTransition).isNull()
- assertThat(state.transitionState.currentScene).isEqualTo(SceneA)
+ assertThat(state.transitionState).isIdle()
+ assertThat(state.transitionState).hasCurrentScene(SceneA)
// Specific transition from A to B.
assertThat(
@@ -477,23 +478,24 @@
overscroll(SceneB, Orientation.Vertical) { fade(TestElements.Foo) }
}
)
- assertThat(state.currentTransition?.currentOverscrollSpec).isNull()
+ val transition = assertThat(state.transitionState).isTransition()
+ assertThat(transition).hasNoOverscrollSpec()
// overscroll for SceneA is NOT defined
progress.value = -0.1f
- assertThat(state.currentTransition?.currentOverscrollSpec).isNull()
+ assertThat(transition).hasNoOverscrollSpec()
// scroll from SceneA to SceneB
progress.value = 0.5f
- assertThat(state.currentTransition?.currentOverscrollSpec).isNull()
+ assertThat(transition).hasNoOverscrollSpec()
progress.value = 1f
- assertThat(state.currentTransition?.currentOverscrollSpec).isNull()
+ assertThat(transition).hasNoOverscrollSpec()
// overscroll for SceneB is defined
progress.value = 1.1f
- assertThat(state.currentTransition?.currentOverscrollSpec).isNotNull()
- assertThat(state.currentTransition?.currentOverscrollSpec?.scene).isEqualTo(SceneB)
+ val overscrollSpec = assertThat(transition).hasOverscrollSpec()
+ assertThat(overscrollSpec.scene).isEqualTo(SceneB)
}
@Test
@@ -507,23 +509,25 @@
overscroll(SceneA, Orientation.Vertical) { fade(TestElements.Foo) }
}
)
- assertThat(state.currentTransition?.currentOverscrollSpec).isNull()
+
+ val transition = assertThat(state.transitionState).isTransition()
+ assertThat(transition).hasNoOverscrollSpec()
// overscroll for SceneA is defined
progress.value = -0.1f
- assertThat(state.currentTransition?.currentOverscrollSpec).isNotNull()
- assertThat(state.currentTransition?.currentOverscrollSpec?.scene).isEqualTo(SceneA)
+ val overscrollSpec = assertThat(transition).hasOverscrollSpec()
+ assertThat(overscrollSpec.scene).isEqualTo(SceneA)
// scroll from SceneA to SceneB
progress.value = 0.5f
- assertThat(state.currentTransition?.currentOverscrollSpec).isNull()
+ assertThat(transition).hasNoOverscrollSpec()
progress.value = 1f
- assertThat(state.currentTransition?.currentOverscrollSpec).isNull()
+ assertThat(transition).hasNoOverscrollSpec()
// overscroll for SceneB is NOT defined
progress.value = 1.1f
- assertThat(state.currentTransition?.currentOverscrollSpec).isNull()
+ assertThat(transition).hasNoOverscrollSpec()
}
@Test
@@ -534,22 +538,24 @@
progress = { progress.value },
sceneTransitions = transitions {}
)
- assertThat(state.currentTransition?.currentOverscrollSpec).isNull()
+
+ val transition = assertThat(state.transitionState).isTransition()
+ assertThat(transition).hasNoOverscrollSpec()
// overscroll for SceneA is NOT defined
progress.value = -0.1f
- assertThat(state.currentTransition?.currentOverscrollSpec).isNull()
+ assertThat(transition).hasNoOverscrollSpec()
// scroll from SceneA to SceneB
progress.value = 0.5f
- assertThat(state.currentTransition?.currentOverscrollSpec).isNull()
+ assertThat(transition).hasNoOverscrollSpec()
progress.value = 1f
- assertThat(state.currentTransition?.currentOverscrollSpec).isNull()
+ assertThat(transition).hasNoOverscrollSpec()
// overscroll for SceneB is NOT defined
progress.value = 1.1f
- assertThat(state.currentTransition?.currentOverscrollSpec).isNull()
+ assertThat(transition).hasNoOverscrollSpec()
}
@Test
@@ -629,4 +635,19 @@
Log.setWtfHandler(originalHandler)
}
}
+
+ @Test
+ fun snapToScene() = runMonotonicClockTest {
+ val state = MutableSceneTransitionLayoutState(SceneA)
+
+ // Transition to B.
+ state.setTargetScene(SceneB, coroutineScope = this)
+ val transition = assertThat(state.transitionState).isTransition()
+ assertThat(transition).hasCurrentScene(SceneB)
+
+ // Snap to C.
+ state.snapToScene(SceneC)
+ assertThat(state.transitionState).isIdle()
+ assertThat(state.transitionState).hasCurrentScene(SceneC)
+ }
}
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutTest.kt
index 7836581..692c18b 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutTest.kt
@@ -51,6 +51,7 @@
import com.android.compose.animation.scene.TestScenes.SceneA
import com.android.compose.animation.scene.TestScenes.SceneB
import com.android.compose.animation.scene.TestScenes.SceneC
+import com.android.compose.animation.scene.subjects.assertThat
import com.android.compose.test.assertSizeIsEqualTo
import com.android.compose.test.subjects.DpOffsetSubject
import com.android.compose.test.subjects.assertThat
@@ -147,34 +148,34 @@
rule.onNodeWithText("SceneA").assertIsDisplayed()
rule.onNodeWithText("SceneB").assertDoesNotExist()
rule.onNodeWithText("SceneC").assertDoesNotExist()
- assertThat(layoutState.transitionState).isInstanceOf(TransitionState.Idle::class.java)
- assertThat(layoutState.transitionState.currentScene).isEqualTo(SceneA)
+ assertThat(layoutState.transitionState).isIdle()
+ assertThat(layoutState.transitionState).hasCurrentScene(SceneA)
// Change to scene B. Only that scene is displayed.
currentScene = SceneB
rule.onNodeWithText("SceneA").assertDoesNotExist()
rule.onNodeWithText("SceneB").assertIsDisplayed()
rule.onNodeWithText("SceneC").assertDoesNotExist()
- assertThat(layoutState.transitionState).isInstanceOf(TransitionState.Idle::class.java)
- assertThat(layoutState.transitionState.currentScene).isEqualTo(SceneB)
+ assertThat(layoutState.transitionState).isIdle()
+ assertThat(layoutState.transitionState).hasCurrentScene(SceneB)
}
@Test
fun testBack() {
rule.setContent { TestContent() }
- assertThat(layoutState.transitionState.currentScene).isEqualTo(SceneA)
+ assertThat(layoutState.transitionState).hasCurrentScene(SceneA)
rule.activity.onBackPressed()
rule.waitForIdle()
- assertThat(layoutState.transitionState.currentScene).isEqualTo(SceneB)
+ assertThat(layoutState.transitionState).hasCurrentScene(SceneB)
}
@Test
fun testTransitionState() {
rule.setContent { TestContent() }
- assertThat(layoutState.transitionState).isInstanceOf(TransitionState.Idle::class.java)
- assertThat(layoutState.transitionState.currentScene).isEqualTo(SceneA)
+ assertThat(layoutState.transitionState).isIdle()
+ assertThat(layoutState.transitionState).hasCurrentScene(SceneA)
// We will advance the clock manually.
rule.mainClock.autoAdvance = false
@@ -182,45 +183,38 @@
// Change the current scene. Until composition is triggered, this won't change the layout
// state.
currentScene = SceneB
- assertThat(layoutState.transitionState).isInstanceOf(TransitionState.Idle::class.java)
- assertThat(layoutState.transitionState.currentScene).isEqualTo(SceneA)
+ assertThat(layoutState.transitionState).isIdle()
+ assertThat(layoutState.transitionState).hasCurrentScene(SceneA)
// On the next frame, we will recompose because currentScene changed, which will start the
// transition (i.e. it will change the transitionState to be a Transition) in a
// LaunchedEffect.
rule.mainClock.advanceTimeByFrame()
- assertThat(layoutState.transitionState).isInstanceOf(TransitionState.Transition::class.java)
- val transition = layoutState.transitionState as TransitionState.Transition
- assertThat(transition.fromScene).isEqualTo(SceneA)
- assertThat(transition.toScene).isEqualTo(SceneB)
- assertThat(transition.progress).isEqualTo(0f)
+ val transition = assertThat(layoutState.transitionState).isTransition()
+ assertThat(transition).hasFromScene(SceneA)
+ assertThat(transition).hasToScene(SceneB)
+ assertThat(transition).hasProgress(0f)
// Then, on the next frame, the animator we started gets its initial value and clock
// starting time. We are now at progress = 0f.
rule.mainClock.advanceTimeByFrame()
- assertThat(layoutState.transitionState).isInstanceOf(TransitionState.Transition::class.java)
- assertThat((layoutState.transitionState as TransitionState.Transition).progress)
- .isEqualTo(0f)
+ assertThat(transition).hasProgress(0f)
// The test transition lasts 480ms. 240ms after the start of the transition, we are at
// progress = 0.5f.
rule.mainClock.advanceTimeBy(TestTransitionDuration / 2)
- assertThat(layoutState.transitionState).isInstanceOf(TransitionState.Transition::class.java)
- assertThat((layoutState.transitionState as TransitionState.Transition).progress)
- .isEqualTo(0.5f)
+ assertThat(transition).hasProgress(0.5f)
// (240-16) ms later, i.e. one frame before the transition is finished, we are at
// progress=(480-16)/480.
rule.mainClock.advanceTimeBy(TestTransitionDuration / 2 - 16)
- assertThat(layoutState.transitionState).isInstanceOf(TransitionState.Transition::class.java)
- assertThat((layoutState.transitionState as TransitionState.Transition).progress)
- .isEqualTo((TestTransitionDuration - 16) / 480f)
+ assertThat(transition).hasProgress((TestTransitionDuration - 16) / 480f)
// one frame (16ms) later, the transition is finished and we are in the idle state in scene
// B.
rule.mainClock.advanceTimeByFrame()
- assertThat(layoutState.transitionState).isInstanceOf(TransitionState.Idle::class.java)
- assertThat(layoutState.transitionState.currentScene).isEqualTo(SceneB)
+ assertThat(layoutState.transitionState).isIdle()
+ assertThat(layoutState.transitionState).hasCurrentScene(SceneB)
}
@Test
@@ -261,8 +255,8 @@
// 100.dp. We pause at the middle of the transition, so it should now be 75.dp given that we
// use a linear interpolator. Foo was at (x = layoutSize - 50dp, y = 0) in SceneA and is
// going to (x = 0, y = 0), so the offset should now be half what it was.
- assertThat((layoutState.transitionState as TransitionState.Transition).progress)
- .isEqualTo(0.5f)
+ var transition = assertThat(layoutState.transitionState).isTransition()
+ assertThat(transition).hasProgress(0.5f)
sharedFoo.assertWidthIsEqualTo(75.dp)
sharedFoo.assertHeightIsEqualTo(75.dp)
sharedFoo.assertPositionInRootIsEqualTo(
@@ -290,8 +284,8 @@
val expectedSize = 100.dp + (150.dp - 100.dp) * interpolatedProgress
sharedFoo = rule.onNode(isElement(TestElements.Foo, SceneC))
- assertThat((layoutState.transitionState as TransitionState.Transition).progress)
- .isEqualTo(interpolatedProgress)
+ transition = assertThat(layoutState.transitionState).isTransition()
+ assertThat(transition).hasProgress(interpolatedProgress)
sharedFoo.assertWidthIsEqualTo(expectedSize)
sharedFoo.assertHeightIsEqualTo(expectedSize)
sharedFoo.assertPositionInRootIsEqualTo(expectedLeft, expectedTop)
@@ -305,16 +299,16 @@
// Wait for the transition to C to finish.
rule.mainClock.advanceTimeBy(TestTransitionDuration)
- assertThat(layoutState.transitionState).isInstanceOf(TransitionState.Idle::class.java)
- assertThat(layoutState.transitionState.currentScene).isEqualTo(SceneC)
+ assertThat(layoutState.transitionState).isIdle()
+ assertThat(layoutState.transitionState).hasCurrentScene(SceneC)
// Go back to scene A. This should happen instantly (once the animation started, i.e. after
// 2 frames) given that we use a snap() animation spec.
currentScene = SceneA
rule.mainClock.advanceTimeByFrame()
rule.mainClock.advanceTimeByFrame()
- assertThat(layoutState.transitionState).isInstanceOf(TransitionState.Idle::class.java)
- assertThat(layoutState.transitionState.currentScene).isEqualTo(SceneA)
+ assertThat(layoutState.transitionState).isIdle()
+ assertThat(layoutState.transitionState).hasCurrentScene(SceneA)
}
@Test
@@ -384,7 +378,9 @@
rule.mainClock.advanceTimeByFrame()
rule.mainClock.advanceTimeBy(duration / 2)
rule.waitForIdle()
- assertThat(state.currentTransition?.progress).isEqualTo(0.5f)
+
+ var transition = assertThat(state.transitionState).isTransition()
+ assertThat(transition).hasProgress(0.5f)
// A and B are composed.
rule.onNodeWithTag("aRoot").assertExists()
@@ -396,7 +392,9 @@
rule.mainClock.advanceTimeByFrame()
rule.mainClock.advanceTimeByFrame()
rule.waitForIdle()
- assertThat(state.currentTransition?.progress).isEqualTo(0f)
+
+ transition = assertThat(state.transitionState).isTransition()
+ assertThat(transition).hasProgress(0f)
// A, B and C are composed.
rule.onNodeWithTag("aRoot").assertExists()
@@ -405,7 +403,7 @@
// Let A => B finish.
rule.mainClock.advanceTimeBy(duration / 2L)
- assertThat(state.currentTransition?.progress).isEqualTo(0.5f)
+ assertThat(transition).hasProgress(0.5f)
rule.waitForIdle()
// B and C are composed.
@@ -416,8 +414,8 @@
// Let B => C finish.
rule.mainClock.advanceTimeBy(duration / 2L)
rule.mainClock.advanceTimeByFrame()
- assertThat(state.currentTransition).isNull()
rule.waitForIdle()
+ assertThat(state.transitionState).isIdle()
// Only C is composed.
rule.onNodeWithTag("aRoot").assertDoesNotExist()
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt
index f034c18..1dd9322 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt
@@ -38,6 +38,9 @@
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.dp
import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.compose.animation.scene.TestScenes.SceneA
+import com.android.compose.animation.scene.TestScenes.SceneB
+import com.android.compose.animation.scene.subjects.assertThat
import com.google.common.truth.Truth.assertThat
import org.junit.Rule
import org.junit.Test
@@ -65,7 +68,7 @@
@get:Rule val rule = createComposeRule()
private fun layoutState(
- initialScene: SceneKey = TestScenes.SceneA,
+ initialScene: SceneKey = SceneA,
transitions: SceneTransitions = EmptyTestTransitions,
) = MutableSceneTransitionLayoutState(initialScene, transitions)
@@ -80,22 +83,21 @@
modifier = Modifier.size(LayoutWidth, LayoutHeight).testTag(TestElements.Foo.debugName),
) {
scene(
- TestScenes.SceneA,
+ SceneA,
userActions =
if (swipesEnabled())
mapOf(
- Swipe.Left to TestScenes.SceneB,
+ Swipe.Left to SceneB,
Swipe.Down to TestScenes.SceneC,
- Swipe.Up to TestScenes.SceneB,
+ Swipe.Up to SceneB,
)
else emptyMap(),
) {
Box(Modifier.fillMaxSize())
}
scene(
- TestScenes.SceneB,
- userActions =
- if (swipesEnabled()) mapOf(Swipe.Right to TestScenes.SceneA) else emptyMap(),
+ SceneB,
+ userActions = if (swipesEnabled()) mapOf(Swipe.Right to SceneA) else emptyMap(),
) {
Box(Modifier.fillMaxSize())
}
@@ -104,11 +106,10 @@
userActions =
if (swipesEnabled())
mapOf(
- Swipe.Down to TestScenes.SceneA,
- Swipe(SwipeDirection.Down, pointerCount = 2) to TestScenes.SceneB,
- Swipe(SwipeDirection.Right, fromSource = Edge.Left) to
- TestScenes.SceneB,
- Swipe(SwipeDirection.Down, fromSource = Edge.Top) to TestScenes.SceneB,
+ Swipe.Down to SceneA,
+ Swipe(SwipeDirection.Down, pointerCount = 2) to SceneB,
+ Swipe(SwipeDirection.Right, fromSource = Edge.Left) to SceneB,
+ Swipe(SwipeDirection.Down, fromSource = Edge.Top) to SceneB,
)
else emptyMap(),
) {
@@ -129,8 +130,8 @@
TestContent(layoutState)
}
- assertThat(layoutState.transitionState).isInstanceOf(TransitionState.Idle::class.java)
- assertThat(layoutState.transitionState.currentScene).isEqualTo(TestScenes.SceneA)
+ assertThat(layoutState.transitionState).isIdle()
+ assertThat(layoutState.transitionState).hasCurrentScene(SceneA)
// Drag left (i.e. from right to left) by 55dp. We pick 55dp here because 56dp is the
// positional threshold from which we commit the gesture.
@@ -144,31 +145,27 @@
// We should be at a progress = 55dp / LayoutWidth given that we use the layout size in
// the gesture axis as swipe distance.
- var transition = layoutState.transitionState
- assertThat(transition).isInstanceOf(TransitionState.Transition::class.java)
- assertThat((transition as TransitionState.Transition).fromScene)
- .isEqualTo(TestScenes.SceneA)
- assertThat(transition.toScene).isEqualTo(TestScenes.SceneB)
- assertThat(transition.currentScene).isEqualTo(TestScenes.SceneA)
- assertThat(transition.progress).isEqualTo(55.dp / LayoutWidth)
- assertThat(transition.isInitiatedByUserInput).isTrue()
+ var transition = assertThat(layoutState.transitionState).isTransition()
+ assertThat(transition).hasFromScene(SceneA)
+ assertThat(transition).hasToScene(SceneB)
+ assertThat(transition).hasCurrentScene(SceneA)
+ assertThat(transition).hasProgress(55.dp / LayoutWidth)
+ assertThat(transition).isInitiatedByUserInput()
// Release the finger. We should now be animating back to A (currentScene = SceneA) given
// that 55dp < positional threshold.
rule.onRoot().performTouchInput { up() }
- transition = layoutState.transitionState
- assertThat(transition).isInstanceOf(TransitionState.Transition::class.java)
- assertThat((transition as TransitionState.Transition).fromScene)
- .isEqualTo(TestScenes.SceneA)
- assertThat(transition.toScene).isEqualTo(TestScenes.SceneB)
- assertThat(transition.currentScene).isEqualTo(TestScenes.SceneA)
- assertThat(transition.progress).isEqualTo(55.dp / LayoutWidth)
- assertThat(transition.isInitiatedByUserInput).isTrue()
+ transition = assertThat(layoutState.transitionState).isTransition()
+ assertThat(transition).hasFromScene(SceneA)
+ assertThat(transition).hasToScene(SceneB)
+ assertThat(transition).hasCurrentScene(SceneA)
+ assertThat(transition).hasProgress(55.dp / LayoutWidth)
+ assertThat(transition).isInitiatedByUserInput()
// Wait for the animation to finish. We should now be in scene A.
rule.waitForIdle()
- assertThat(layoutState.transitionState).isInstanceOf(TransitionState.Idle::class.java)
- assertThat(layoutState.transitionState.currentScene).isEqualTo(TestScenes.SceneA)
+ assertThat(layoutState.transitionState).isIdle()
+ assertThat(layoutState.transitionState).hasCurrentScene(SceneA)
// Now we do the same but vertically and with a drag distance of 56dp, which is >=
// positional threshold.
@@ -178,31 +175,27 @@
}
// Drag is in progress, so currentScene = SceneA and progress = 56dp / LayoutHeight
- transition = layoutState.transitionState
- assertThat(transition).isInstanceOf(TransitionState.Transition::class.java)
- assertThat((transition as TransitionState.Transition).fromScene)
- .isEqualTo(TestScenes.SceneA)
- assertThat(transition.toScene).isEqualTo(TestScenes.SceneC)
- assertThat(transition.currentScene).isEqualTo(TestScenes.SceneA)
- assertThat(transition.progress).isEqualTo(56.dp / LayoutHeight)
- assertThat(transition.isInitiatedByUserInput).isTrue()
+ transition = assertThat(layoutState.transitionState).isTransition()
+ assertThat(transition).hasFromScene(SceneA)
+ assertThat(transition).hasToScene(TestScenes.SceneC)
+ assertThat(transition).hasCurrentScene(SceneA)
+ assertThat(transition).hasProgress(56.dp / LayoutHeight)
+ assertThat(transition).isInitiatedByUserInput()
// Release the finger. We should now be animating to C (currentScene = SceneC) given
// that 56dp >= positional threshold.
rule.onRoot().performTouchInput { up() }
- transition = layoutState.transitionState
- assertThat(transition).isInstanceOf(TransitionState.Transition::class.java)
- assertThat((transition as TransitionState.Transition).fromScene)
- .isEqualTo(TestScenes.SceneA)
- assertThat(transition.toScene).isEqualTo(TestScenes.SceneC)
- assertThat(transition.currentScene).isEqualTo(TestScenes.SceneC)
- assertThat(transition.progress).isEqualTo(56.dp / LayoutHeight)
- assertThat(transition.isInitiatedByUserInput).isTrue()
+ transition = assertThat(layoutState.transitionState).isTransition()
+ assertThat(transition).hasFromScene(SceneA)
+ assertThat(transition).hasToScene(TestScenes.SceneC)
+ assertThat(transition).hasCurrentScene(TestScenes.SceneC)
+ assertThat(transition).hasProgress(56.dp / LayoutHeight)
+ assertThat(transition).isInitiatedByUserInput()
// Wait for the animation to finish. We should now be in scene C.
rule.waitForIdle()
- assertThat(layoutState.transitionState).isInstanceOf(TransitionState.Idle::class.java)
- assertThat(layoutState.transitionState.currentScene).isEqualTo(TestScenes.SceneC)
+ assertThat(layoutState.transitionState).isIdle()
+ assertThat(layoutState.transitionState).hasCurrentScene(TestScenes.SceneC)
}
@Test
@@ -216,8 +209,8 @@
TestContent(layoutState)
}
- assertThat(layoutState.transitionState).isInstanceOf(TransitionState.Idle::class.java)
- assertThat(layoutState.transitionState.currentScene).isEqualTo(TestScenes.SceneA)
+ assertThat(layoutState.transitionState).isIdle()
+ assertThat(layoutState.transitionState).hasCurrentScene(SceneA)
// Swipe left (i.e. from right to left) using a velocity of 124 dp/s. We pick 124 dp/s here
// because 125 dp/s is the velocity threshold from which we commit the gesture. We also use
@@ -233,18 +226,16 @@
// We should be animating back to A (currentScene = SceneA) given that 124 dp/s < velocity
// threshold.
- var transition = layoutState.transitionState
- assertThat(transition).isInstanceOf(TransitionState.Transition::class.java)
- assertThat((transition as TransitionState.Transition).fromScene)
- .isEqualTo(TestScenes.SceneA)
- assertThat(transition.toScene).isEqualTo(TestScenes.SceneB)
- assertThat(transition.currentScene).isEqualTo(TestScenes.SceneA)
- assertThat(transition.progress).isEqualTo(55.dp / LayoutWidth)
+ var transition = assertThat(layoutState.transitionState).isTransition()
+ assertThat(transition).hasFromScene(SceneA)
+ assertThat(transition).hasToScene(SceneB)
+ assertThat(transition).hasCurrentScene(SceneA)
+ assertThat(transition).hasProgress(55.dp / LayoutWidth)
// Wait for the animation to finish. We should now be in scene A.
rule.waitForIdle()
- assertThat(layoutState.transitionState).isInstanceOf(TransitionState.Idle::class.java)
- assertThat(layoutState.transitionState.currentScene).isEqualTo(TestScenes.SceneA)
+ assertThat(layoutState.transitionState).isIdle()
+ assertThat(layoutState.transitionState).hasCurrentScene(SceneA)
// Now we do the same but vertically and with a swipe velocity of 126dp, which is >
// velocity threshold. Note that in theory we could have used 125 dp (= velocity threshold)
@@ -259,18 +250,16 @@
}
// We should be animating to C (currentScene = SceneC).
- transition = layoutState.transitionState
- assertThat(transition).isInstanceOf(TransitionState.Transition::class.java)
- assertThat((transition as TransitionState.Transition).fromScene)
- .isEqualTo(TestScenes.SceneA)
- assertThat(transition.toScene).isEqualTo(TestScenes.SceneC)
- assertThat(transition.currentScene).isEqualTo(TestScenes.SceneC)
- assertThat(transition.progress).isEqualTo(55.dp / LayoutHeight)
+ transition = assertThat(layoutState.transitionState).isTransition()
+ assertThat(transition).hasFromScene(SceneA)
+ assertThat(transition).hasToScene(TestScenes.SceneC)
+ assertThat(transition).hasCurrentScene(TestScenes.SceneC)
+ assertThat(transition).hasProgress(55.dp / LayoutHeight)
// Wait for the animation to finish. We should now be in scene C.
rule.waitForIdle()
- assertThat(layoutState.transitionState).isInstanceOf(TransitionState.Idle::class.java)
- assertThat(layoutState.transitionState.currentScene).isEqualTo(TestScenes.SceneC)
+ assertThat(layoutState.transitionState).isIdle()
+ assertThat(layoutState.transitionState).hasCurrentScene(TestScenes.SceneC)
}
@Test
@@ -286,8 +275,8 @@
TestContent(layoutState)
}
- assertThat(layoutState.transitionState).isInstanceOf(TransitionState.Idle::class.java)
- assertThat(layoutState.transitionState.currentScene).isEqualTo(TestScenes.SceneC)
+ assertThat(layoutState.transitionState).isIdle()
+ assertThat(layoutState.transitionState).hasCurrentScene(TestScenes.SceneC)
// Swipe down with two fingers.
rule.onRoot().performTouchInput {
@@ -298,18 +287,16 @@
}
// We are transitioning to B because we used 2 fingers.
- val transition = layoutState.transitionState
- assertThat(transition).isInstanceOf(TransitionState.Transition::class.java)
- assertThat((transition as TransitionState.Transition).fromScene)
- .isEqualTo(TestScenes.SceneC)
- assertThat(transition.toScene).isEqualTo(TestScenes.SceneB)
+ val transition = assertThat(layoutState.transitionState).isTransition()
+ assertThat(transition).hasFromScene(TestScenes.SceneC)
+ assertThat(transition).hasToScene(SceneB)
// Release the fingers and wait for the animation to end. We are back to C because we only
// swiped 10dp.
rule.onRoot().performTouchInput { repeat(2) { i -> up(pointerId = i) } }
rule.waitForIdle()
- assertThat(layoutState.transitionState).isInstanceOf(TransitionState.Idle::class.java)
- assertThat(layoutState.transitionState.currentScene).isEqualTo(TestScenes.SceneC)
+ assertThat(layoutState.transitionState).isIdle()
+ assertThat(layoutState.transitionState).hasCurrentScene(TestScenes.SceneC)
}
@Test
@@ -325,8 +312,8 @@
TestContent(layoutState)
}
- assertThat(layoutState.transitionState).isInstanceOf(TransitionState.Idle::class.java)
- assertThat(layoutState.transitionState.currentScene).isEqualTo(TestScenes.SceneC)
+ assertThat(layoutState.transitionState).isIdle()
+ assertThat(layoutState.transitionState).hasCurrentScene(TestScenes.SceneC)
// Swipe down from the top edge.
rule.onRoot().performTouchInput {
@@ -335,18 +322,16 @@
}
// We are transitioning to B (and not A) because we started from the top edge.
- var transition = layoutState.transitionState
- assertThat(transition).isInstanceOf(TransitionState.Transition::class.java)
- assertThat((transition as TransitionState.Transition).fromScene)
- .isEqualTo(TestScenes.SceneC)
- assertThat(transition.toScene).isEqualTo(TestScenes.SceneB)
+ var transition = assertThat(layoutState.transitionState).isTransition()
+ assertThat(transition).hasFromScene(TestScenes.SceneC)
+ assertThat(transition).hasToScene(SceneB)
// Release the fingers and wait for the animation to end. We are back to C because we only
// swiped 10dp.
rule.onRoot().performTouchInput { up() }
rule.waitForIdle()
- assertThat(layoutState.transitionState).isInstanceOf(TransitionState.Idle::class.java)
- assertThat(layoutState.transitionState.currentScene).isEqualTo(TestScenes.SceneC)
+ assertThat(layoutState.transitionState).isIdle()
+ assertThat(layoutState.transitionState).hasCurrentScene(TestScenes.SceneC)
// Swipe right from the left edge.
rule.onRoot().performTouchInput {
@@ -355,18 +340,16 @@
}
// We are transitioning to B (and not A) because we started from the left edge.
- transition = layoutState.transitionState
- assertThat(transition).isInstanceOf(TransitionState.Transition::class.java)
- assertThat((transition as TransitionState.Transition).fromScene)
- .isEqualTo(TestScenes.SceneC)
- assertThat(transition.toScene).isEqualTo(TestScenes.SceneB)
+ transition = assertThat(layoutState.transitionState).isTransition()
+ assertThat(transition).hasFromScene(TestScenes.SceneC)
+ assertThat(transition).hasToScene(SceneB)
// Release the fingers and wait for the animation to end. We are back to C because we only
// swiped 10dp.
rule.onRoot().performTouchInput { up() }
rule.waitForIdle()
- assertThat(layoutState.transitionState).isInstanceOf(TransitionState.Idle::class.java)
- assertThat(layoutState.transitionState.currentScene).isEqualTo(TestScenes.SceneC)
+ assertThat(layoutState.transitionState).isIdle()
+ assertThat(layoutState.transitionState).hasCurrentScene(TestScenes.SceneC)
}
@Test
@@ -380,7 +363,7 @@
layoutState(
transitions =
transitions {
- from(TestScenes.SceneA, to = TestScenes.SceneB) {
+ from(SceneA, to = SceneB) {
distance = FixedDistance(verticalSwipeDistance)
}
}
@@ -395,12 +378,12 @@
modifier = Modifier.size(LayoutWidth, LayoutHeight)
) {
scene(
- TestScenes.SceneA,
- userActions = mapOf(Swipe.Down to TestScenes.SceneB),
+ SceneA,
+ userActions = mapOf(Swipe.Down to SceneB),
) {
Spacer(Modifier.fillMaxSize())
}
- scene(TestScenes.SceneB) { Spacer(Modifier.fillMaxSize()) }
+ scene(SceneB) { Spacer(Modifier.fillMaxSize()) }
}
}
@@ -413,9 +396,9 @@
}
// We should be at 50%
- val transition = layoutState.currentTransition
+ val transition = assertThat(layoutState.transitionState).isTransition()
assertThat(transition).isNotNull()
- assertThat(transition!!.progress).isEqualTo(0.5f)
+ assertThat(transition).hasProgress(0.5f)
}
@Test
@@ -434,15 +417,14 @@
}
// We should still correctly compute that we are swiping down to scene C.
- var transition = layoutState.currentTransition
- assertThat(transition).isNotNull()
- assertThat(transition?.toScene).isEqualTo(TestScenes.SceneC)
+ var transition = assertThat(layoutState.transitionState).isTransition()
+ assertThat(transition).hasToScene(TestScenes.SceneC)
// Release the finger, animating back to scene A.
rule.onRoot().performTouchInput { up() }
rule.waitForIdle()
- assertThat(layoutState.currentTransition).isNull()
- assertThat(layoutState.transitionState.currentScene).isEqualTo(TestScenes.SceneA)
+ assertThat(layoutState.transitionState).isIdle()
+ assertThat(layoutState.transitionState).hasCurrentScene(SceneA)
// Swipe up by exactly touchSlop, so that the drag overSlop is 0f.
rule.onRoot().performTouchInput {
@@ -451,15 +433,14 @@
}
// We should still correctly compute that we are swiping up to scene B.
- transition = layoutState.currentTransition
- assertThat(transition).isNotNull()
- assertThat(transition?.toScene).isEqualTo(TestScenes.SceneB)
+ transition = assertThat(layoutState.transitionState).isTransition()
+ assertThat(transition).hasToScene(SceneB)
// Release the finger, animating back to scene A.
rule.onRoot().performTouchInput { up() }
rule.waitForIdle()
- assertThat(layoutState.currentTransition).isNull()
- assertThat(layoutState.transitionState.currentScene).isEqualTo(TestScenes.SceneA)
+ assertThat(layoutState.transitionState).isIdle()
+ assertThat(layoutState.transitionState).hasCurrentScene(SceneA)
// Swipe left by exactly touchSlop, so that the drag overSlop is 0f.
rule.onRoot().performTouchInput {
@@ -468,14 +449,13 @@
}
// We should still correctly compute that we are swiping down to scene B.
- transition = layoutState.currentTransition
- assertThat(transition).isNotNull()
- assertThat(transition?.toScene).isEqualTo(TestScenes.SceneB)
+ transition = assertThat(layoutState.transitionState).isTransition()
+ assertThat(transition).hasToScene(SceneB)
}
@Test
fun swipeEnabledLater() {
- val layoutState = MutableSceneTransitionLayoutState(TestScenes.SceneA)
+ val layoutState = MutableSceneTransitionLayoutState(SceneA)
var swipesEnabled by mutableStateOf(false)
var touchSlop = 0f
rule.setContent {
@@ -509,34 +489,32 @@
fun transitionKey() {
val transitionkey = TransitionKey(debugName = "foo")
val state =
- MutableSceneTransitionLayoutState(
- TestScenes.SceneA,
+ MutableSceneTransitionLayoutStateImpl(
+ SceneA,
transitions {
- from(TestScenes.SceneA, to = TestScenes.SceneB) { fade(TestElements.Foo) }
- from(TestScenes.SceneA, to = TestScenes.SceneB, key = transitionkey) {
+ from(SceneA, to = SceneB) { fade(TestElements.Foo) }
+ from(SceneA, to = SceneB, key = transitionkey) {
fade(TestElements.Foo)
fade(TestElements.Bar)
}
}
)
- as MutableSceneTransitionLayoutStateImpl
var touchSlop = 0f
rule.setContent {
touchSlop = LocalViewConfiguration.current.touchSlop
SceneTransitionLayout(state, Modifier.size(LayoutWidth, LayoutHeight)) {
scene(
- TestScenes.SceneA,
+ SceneA,
userActions =
mapOf(
- Swipe.Down to TestScenes.SceneB,
- Swipe.Up to
- UserActionResult(TestScenes.SceneB, transitionKey = transitionkey)
+ Swipe.Down to SceneB,
+ Swipe.Up to UserActionResult(SceneB, transitionKey = transitionkey)
)
) {
Box(Modifier.fillMaxSize())
}
- scene(TestScenes.SceneB) { Box(Modifier.fillMaxSize()) }
+ scene(SceneB) { Box(Modifier.fillMaxSize()) }
}
}
@@ -546,12 +524,12 @@
moveBy(Offset(0f, touchSlop), delayMillis = 1_000)
}
- assertThat(state.isTransitioning(from = TestScenes.SceneA, to = TestScenes.SceneB)).isTrue()
+ assertThat(state.isTransitioning(from = SceneA, to = SceneB)).isTrue()
assertThat(state.currentTransition?.transformationSpec?.transformations).hasSize(1)
// Move the pointer up to swipe to scene B using the new transition.
rule.onRoot().performTouchInput { moveBy(Offset(0f, -1.dp.toPx()), delayMillis = 1_000) }
- assertThat(state.isTransitioning(from = TestScenes.SceneA, to = TestScenes.SceneB)).isTrue()
+ assertThat(state.isTransitioning(from = SceneA, to = SceneB)).isTrue()
assertThat(state.currentTransition?.transformationSpec?.transformations).hasSize(2)
}
@@ -567,19 +545,17 @@
// the difference between the bottom of the scene and the bottom of the element,
// so that we use the offset and size of the element as well as the size of the
// scene.
- val fooSize = TestElements.Foo.targetSize(TestScenes.SceneB) ?: return 0f
- val fooOffset = TestElements.Foo.targetOffset(TestScenes.SceneB) ?: return 0f
- val sceneSize = TestScenes.SceneB.targetSize() ?: return 0f
+ val fooSize = TestElements.Foo.targetSize(SceneB) ?: return 0f
+ val fooOffset = TestElements.Foo.targetOffset(SceneB) ?: return 0f
+ val sceneSize = SceneB.targetSize() ?: return 0f
return sceneSize.height - fooOffset.y - fooSize.height
}
}
val state =
MutableSceneTransitionLayoutState(
- TestScenes.SceneA,
- transitions {
- from(TestScenes.SceneA, to = TestScenes.SceneB) { distance = swipeDistance }
- }
+ SceneA,
+ transitions { from(SceneA, to = SceneB) { distance = swipeDistance } }
)
val layoutSize = 200.dp
@@ -591,10 +567,10 @@
touchSlop = LocalViewConfiguration.current.touchSlop
SceneTransitionLayout(state, Modifier.size(layoutSize)) {
- scene(TestScenes.SceneA, userActions = mapOf(Swipe.Up to TestScenes.SceneB)) {
+ scene(SceneA, userActions = mapOf(Swipe.Up to SceneB)) {
Box(Modifier.fillMaxSize())
}
- scene(TestScenes.SceneB) {
+ scene(SceneB) {
Box(Modifier.fillMaxSize()) {
Box(Modifier.offset(y = fooYOffset).element(TestElements.Foo).size(fooSize))
}
@@ -611,7 +587,9 @@
}
rule.waitForIdle()
- assertThat(state.isTransitioning(from = TestScenes.SceneA, to = TestScenes.SceneB)).isTrue()
- assertThat(state.currentTransition!!.progress).isWithin(0.01f).of(0.5f)
+ val transition = assertThat(state.transitionState).isTransition()
+ assertThat(transition).hasFromScene(SceneA)
+ assertThat(transition).hasToScene(SceneB)
+ assertThat(transition).hasProgress(0.5f, tolerance = 0.01f)
}
}
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/Transition.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/Transition.kt
index c1218ae..a609be4 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/Transition.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/Transition.kt
@@ -27,7 +27,9 @@
fun transition(
from: SceneKey,
to: SceneKey,
+ current: () -> SceneKey = { from },
progress: () -> Float = { 0f },
+ progressVelocity: () -> Float = { 0f },
interruptionProgress: () -> Float = { 100f },
isInitiatedByUserInput: Boolean = false,
isUserInputOngoing: Boolean = false,
@@ -37,9 +39,12 @@
onFinish: ((TransitionState.Transition) -> Job)? = null,
): TransitionState.Transition {
return object : TransitionState.Transition(from, to), TransitionState.HasOverscrollProperties {
- override val currentScene: SceneKey = from
+ override val currentScene: SceneKey
+ get() = current()
override val progress: Float
get() = progress()
+ override val progressVelocity: Float
+ get() = progressVelocity()
override val isInitiatedByUserInput: Boolean = isInitiatedByUserInput
override val isUserInputOngoing: Boolean = isUserInputOngoing
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/subjects/TransitionStateSubject.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/subjects/TransitionStateSubject.kt
new file mode 100644
index 0000000..3489892
--- /dev/null
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/subjects/TransitionStateSubject.kt
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.compose.animation.scene.subjects
+
+import com.android.compose.animation.scene.OverscrollSpec
+import com.android.compose.animation.scene.SceneKey
+import com.android.compose.animation.scene.TransitionState
+import com.google.common.truth.Fact.simpleFact
+import com.google.common.truth.FailureMetadata
+import com.google.common.truth.Subject
+import com.google.common.truth.Subject.Factory
+import com.google.common.truth.Truth
+
+/** Assert on a [TransitionState]. */
+fun assertThat(state: TransitionState): TransitionStateSubject {
+ return Truth.assertAbout(TransitionStateSubject.transitionStates()).that(state)
+}
+
+/** Assert on a [TransitionState.Transition]. */
+fun assertThat(transitions: TransitionState.Transition): TransitionSubject {
+ return Truth.assertAbout(TransitionSubject.transitions()).that(transitions)
+}
+
+class TransitionStateSubject
+private constructor(
+ metadata: FailureMetadata,
+ private val actual: TransitionState,
+) : Subject(metadata, actual) {
+ fun hasCurrentScene(sceneKey: SceneKey) {
+ check("currentScene").that(actual.currentScene).isEqualTo(sceneKey)
+ }
+
+ fun isIdle(): TransitionState.Idle {
+ if (actual !is TransitionState.Idle) {
+ failWithActual(simpleFact("expected to be TransitionState.Idle"))
+ }
+
+ return actual as TransitionState.Idle
+ }
+
+ fun isTransition(): TransitionState.Transition {
+ if (actual !is TransitionState.Transition) {
+ failWithActual(simpleFact("expected to be TransitionState.Transition"))
+ }
+
+ return actual as TransitionState.Transition
+ }
+
+ companion object {
+ fun transitionStates() = Factory { metadata, actual: TransitionState ->
+ TransitionStateSubject(metadata, actual)
+ }
+ }
+}
+
+class TransitionSubject
+private constructor(
+ metadata: FailureMetadata,
+ private val actual: TransitionState.Transition,
+) : Subject(metadata, actual) {
+ fun hasCurrentScene(sceneKey: SceneKey) {
+ check("currentScene").that(actual.currentScene).isEqualTo(sceneKey)
+ }
+
+ fun hasFromScene(sceneKey: SceneKey) {
+ check("fromScene").that(actual.fromScene).isEqualTo(sceneKey)
+ }
+
+ fun hasToScene(sceneKey: SceneKey) {
+ check("toScene").that(actual.toScene).isEqualTo(sceneKey)
+ }
+
+ fun hasProgress(progress: Float, tolerance: Float = 0f) {
+ check("progress").that(actual.progress).isWithin(tolerance).of(progress)
+ }
+
+ fun hasProgressVelocity(progressVelocity: Float, tolerance: Float = 0f) {
+ check("progressVelocity")
+ .that(actual.progressVelocity)
+ .isWithin(tolerance)
+ .of(progressVelocity)
+ }
+
+ fun isInitiatedByUserInput() {
+ check("isInitiatedByUserInput").that(actual.isInitiatedByUserInput).isTrue()
+ }
+
+ fun hasIsUserInputOngoing(isUserInputOngoing: Boolean) {
+ check("isUserInputOngoing").that(actual.isUserInputOngoing).isEqualTo(isUserInputOngoing)
+ }
+
+ fun hasOverscrollSpec(): OverscrollSpec {
+ check("currentOverscrollSpec").that(actual.currentOverscrollSpec).isNotNull()
+ return actual.currentOverscrollSpec!!
+ }
+
+ fun hasNoOverscrollSpec() {
+ check("currentOverscrollSpec").that(actual.currentOverscrollSpec).isNull()
+ }
+
+ fun hasBouncingScene(scene: SceneKey) {
+ if (actual !is TransitionState.HasOverscrollProperties) {
+ failWithActual(simpleFact("expected to be TransitionState.HasOverscrollProperties"))
+ }
+
+ check("bouncingScene")
+ .that((actual as TransitionState.HasOverscrollProperties).bouncingScene)
+ .isEqualTo(scene)
+ }
+
+ companion object {
+ fun transitions() = Factory { metadata, actual: TransitionState.Transition ->
+ TransitionSubject(metadata, actual)
+ }
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
index aa70c45..6c3f3c1 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
@@ -17,8 +17,11 @@
package com.android.keyguard
+import android.app.admin.DevicePolicyManager
+import android.app.admin.flags.Flags as DevicePolicyFlags
import android.content.res.Configuration
import android.media.AudioManager
+import android.platform.test.annotations.EnableFlags
import android.telephony.TelephonyManager
import android.testing.TestableLooper.RunWithLooper
import android.testing.TestableResources
@@ -148,6 +151,7 @@
@Mock private lateinit var faceAuthAccessibilityDelegate: FaceAuthAccessibilityDelegate
@Mock private lateinit var deviceProvisionedController: DeviceProvisionedController
@Mock private lateinit var postureController: DevicePostureController
+ @Mock private lateinit var devicePolicyManager: DevicePolicyManager
@Captor
private lateinit var swipeListenerArgumentCaptor:
@@ -211,7 +215,6 @@
if (!SceneContainerFlag.isEnabled) {
mSetFlagsRule.disableFlags(
AConfigFlags.FLAG_KEYGUARD_WM_STATE_REFACTOR,
- AConfigFlags.FLAG_REFACTOR_KEYGUARD_DISMISS_INTENT,
)
}
@@ -274,6 +277,7 @@
mSelectedUserInteractor,
deviceProvisionedController,
faceAuthAccessibilityDelegate,
+ devicePolicyManager,
keyguardTransitionInteractor,
{ primaryBouncerInteractor },
) {
@@ -796,6 +800,7 @@
ObservableTransitionState.Transition(
Scenes.Lockscreen,
Scenes.Bouncer,
+ flowOf(Scenes.Bouncer),
flowOf(.5f),
false,
isUserInputOngoing = flowOf(false),
@@ -819,6 +824,7 @@
ObservableTransitionState.Transition(
Scenes.Bouncer,
Scenes.Gone,
+ flowOf(Scenes.Gone),
flowOf(.5f),
false,
isUserInputOngoing = flowOf(false),
@@ -838,6 +844,7 @@
ObservableTransitionState.Transition(
Scenes.Gone,
Scenes.Bouncer,
+ flowOf(Scenes.Bouncer),
flowOf(.5f),
false,
isUserInputOngoing = flowOf(false),
@@ -859,6 +866,7 @@
ObservableTransitionState.Transition(
Scenes.Bouncer,
Scenes.Gone,
+ flowOf(Scenes.Gone),
flowOf(.5f),
false,
isUserInputOngoing = flowOf(false),
@@ -877,6 +885,7 @@
ObservableTransitionState.Transition(
Scenes.Gone,
Scenes.Lockscreen,
+ flowOf(Scenes.Lockscreen),
flowOf(.5f),
false,
isUserInputOngoing = flowOf(false),
@@ -897,6 +906,7 @@
ObservableTransitionState.Transition(
Scenes.Lockscreen,
Scenes.Gone,
+ flowOf(Scenes.Gone),
flowOf(.5f),
false,
isUserInputOngoing = flowOf(false),
@@ -929,6 +939,45 @@
verify(viewFlipperController).asynchronouslyInflateView(any(), any(), any())
}
+ @Test
+ @EnableFlags(DevicePolicyFlags.FLAG_HEADLESS_SINGLE_USER_FIXES)
+ fun showAlmostAtWipeDialog_calledOnMainUser_setsCorrectUserType() {
+ val mainUserId = 10
+
+ underTest.showMessageForFailedUnlockAttempt(
+ /* userId = */ mainUserId,
+ /* expiringUserId = */ mainUserId,
+ /* mainUserId = */ mainUserId,
+ /* remainingBeforeWipe = */ 1,
+ /* failedAttempts = */ 1
+ )
+
+ verify(view)
+ .showAlmostAtWipeDialog(any(), any(), eq(KeyguardSecurityContainer.USER_TYPE_PRIMARY))
+ }
+
+ @Test
+ @EnableFlags(DevicePolicyFlags.FLAG_HEADLESS_SINGLE_USER_FIXES)
+ fun showAlmostAtWipeDialog_calledOnNonMainUser_setsCorrectUserType() {
+ val secondaryUserId = 10
+ val mainUserId = 0
+
+ underTest.showMessageForFailedUnlockAttempt(
+ /* userId = */ secondaryUserId,
+ /* expiringUserId = */ secondaryUserId,
+ /* mainUserId = */ mainUserId,
+ /* remainingBeforeWipe = */ 1,
+ /* failedAttempts = */ 1
+ )
+
+ verify(view)
+ .showAlmostAtWipeDialog(
+ any(),
+ any(),
+ eq(KeyguardSecurityContainer.USER_TYPE_SECONDARY_USER)
+ )
+ }
+
private val registeredSwipeListener: KeyguardSecurityContainer.SwipeListener
get() {
underTest.onViewAttached()
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/data/repository/OneHandedModeRepositoryImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/data/repository/OneHandedModeRepositoryImplTest.kt
new file mode 100644
index 0000000..c0d481c
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/data/repository/OneHandedModeRepositoryImplTest.kt
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.accessibility.data.repository
+
+import android.os.UserHandle
+import android.provider.Settings
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.util.settings.FakeSettings
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+@android.platform.test.annotations.EnabledOnRavenwood
+class OneHandedModeRepositoryImplTest : SysuiTestCase() {
+
+ private val testUser1 = UserHandle.of(1)!!
+ private val testUser2 = UserHandle.of(2)!!
+ private val testDispatcher = StandardTestDispatcher()
+ private val scope = TestScope(testDispatcher)
+ private val settings: FakeSettings = FakeSettings()
+
+ private val underTest: OneHandedModeRepository =
+ OneHandedModeRepositoryImpl(
+ testDispatcher,
+ scope.backgroundScope,
+ settings,
+ )
+
+ @Test
+ fun isEnabled_settingNotInitialized_returnsFalseByDefault() =
+ scope.runTest {
+ val actualValue by collectLastValue(underTest.isEnabled(testUser1))
+
+ runCurrent()
+
+ assertThat(actualValue).isFalse()
+ }
+
+ @Test
+ fun isEnabled_initiallyGetsSettingsValue() =
+ scope.runTest {
+ val actualValue by collectLastValue(underTest.isEnabled(testUser1))
+
+ settings.putIntForUser(SETTING_NAME, ENABLED, testUser1.identifier)
+ runCurrent()
+
+ assertThat(actualValue).isTrue()
+ }
+
+ @Test
+ fun isEnabled_settingUpdated_valueUpdated() =
+ scope.runTest {
+ val actualValue by collectLastValue(underTest.isEnabled(testUser1))
+ runCurrent()
+ assertThat(actualValue).isFalse()
+
+ settings.putIntForUser(SETTING_NAME, ENABLED, testUser1.identifier)
+ runCurrent()
+
+ assertThat(actualValue).isTrue()
+ runCurrent()
+
+ settings.putIntForUser(SETTING_NAME, DISABLED, testUser1.identifier)
+ runCurrent()
+ assertThat(actualValue).isFalse()
+ }
+
+ @Test
+ fun isEnabled_settingForUserOneOnly_valueUpdatedForUserOneOnly() =
+ scope.runTest {
+ val lastValueUser1 by collectLastValue(underTest.isEnabled(testUser1))
+ val lastValueUser2 by collectLastValue(underTest.isEnabled(testUser2))
+
+ settings.putIntForUser(SETTING_NAME, DISABLED, testUser1.identifier)
+ settings.putIntForUser(SETTING_NAME, DISABLED, testUser2.identifier)
+ runCurrent()
+ assertThat(lastValueUser1).isFalse()
+ assertThat(lastValueUser2).isFalse()
+
+ settings.putIntForUser(SETTING_NAME, ENABLED, testUser1.identifier)
+ runCurrent()
+ assertThat(lastValueUser1).isTrue()
+ assertThat(lastValueUser2).isFalse()
+ }
+
+ @Test
+ fun setEnabled() =
+ scope.runTest {
+ val success = underTest.setIsEnabled(true, testUser1)
+ runCurrent()
+ assertThat(success).isTrue()
+
+ val actualValue = settings.getIntForUser(SETTING_NAME, testUser1.identifier)
+ assertThat(actualValue).isEqualTo(ENABLED)
+ }
+
+ @Test
+ fun setDisabled() =
+ scope.runTest {
+ val success = underTest.setIsEnabled(false, testUser1)
+ runCurrent()
+ assertThat(success).isTrue()
+
+ val actualValue = settings.getIntForUser(SETTING_NAME, testUser1.identifier)
+ assertThat(actualValue).isEqualTo(DISABLED)
+ }
+
+ companion object {
+ private const val SETTING_NAME = Settings.Secure.ONE_HANDED_MODE_ENABLED
+ private const val DISABLED = 0
+ private const val ENABLED = 1
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/BouncerSwipeTouchHandlerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/BouncerSwipeTouchHandlerTest.java
index 3395268..630bcd6 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/BouncerSwipeTouchHandlerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/BouncerSwipeTouchHandlerTest.java
@@ -24,6 +24,7 @@
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import android.animation.AnimatorListenerAdapter;
@@ -163,6 +164,7 @@
* Ensures expansion only happens when touch down happens in valid part of the screen.
*/
@Test
+ @DisableFlags(Flags.FLAG_COMMUNAL_BOUNCER_DO_NOT_MODIFY_PLUGIN_OPEN)
public void testSessionStart() {
mTouchHandler.getTouchInitiationRegion(SCREEN_BOUNDS, mRegion, null);
@@ -193,7 +195,31 @@
2)).isTrue();
}
+
+ /**
+ * Ensures expansion only happens when touch down happens in valid part of the screen.
+ */
@Test
+ @EnableFlags(Flags.FLAG_COMMUNAL_BOUNCER_DO_NOT_MODIFY_PLUGIN_OPEN)
+ public void testSessionStart_doesNotModifyNotificationShadeWindow() {
+ mTouchHandler.getTouchInitiationRegion(SCREEN_BOUNDS, mRegion, null);
+
+ verify(mRegion).union(mRectCaptor.capture());
+ final Rect bounds = mRectCaptor.getValue();
+
+ final Rect expected = new Rect();
+
+ expected.set(0, Math.round(SCREEN_HEIGHT_PX * (1 - TOUCH_REGION)), SCREEN_WIDTH_PX,
+ SCREEN_HEIGHT_PX);
+
+ assertThat(bounds).isEqualTo(expected);
+
+ mTouchHandler.onSessionStart(mTouchSession);
+ verifyNoMoreInteractions(mNotificationShadeWindowController);
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_COMMUNAL_BOUNCER_DO_NOT_MODIFY_PLUGIN_OPEN)
public void testSwipeUp_whenBouncerInitiallyShowing_reduceHeightWithExclusionRects() {
mTouchHandler.getTouchInitiationRegion(SCREEN_BOUNDS, mRegion,
new Rect(0, 0, SCREEN_WIDTH_PX, SCREEN_HEIGHT_PX));
@@ -213,6 +239,7 @@
}
@Test
+ @DisableFlags(Flags.FLAG_COMMUNAL_BOUNCER_DO_NOT_MODIFY_PLUGIN_OPEN)
public void testSwipeUp_exclusionRectAtTop_doesNotIntersectGestureArea() {
mTouchHandler.getTouchInitiationRegion(SCREEN_BOUNDS, mRegion,
new Rect(0, 0, SCREEN_WIDTH_PX, SCREEN_HEIGHT_PX / 4));
@@ -228,6 +255,7 @@
}
@Test
+ @DisableFlags(Flags.FLAG_COMMUNAL_BOUNCER_DO_NOT_MODIFY_PLUGIN_OPEN)
public void testSwipeUp_exclusionRectBetweenNormalAndMinimumSwipeArea() {
final int normalSwipeAreaTop = SCREEN_HEIGHT_PX
- Math.round(SCREEN_HEIGHT_PX * TOUCH_REGION);
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt
index 81878aa..0c5e726 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt
@@ -17,6 +17,8 @@
package com.android.systemui.authentication.domain.interactor
import android.app.admin.DevicePolicyManager
+import android.app.admin.flags.Flags as DevicePolicyFlags
+import android.platform.test.annotations.EnableFlags
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.internal.widget.LockPatternUtils
@@ -32,6 +34,8 @@
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.kosmos.testScope
import com.android.systemui.testKosmos
+import com.android.systemui.user.data.repository.FakeUserRepository
+import com.android.systemui.user.data.repository.fakeUserRepository
import com.google.common.truth.Truth.assertThat
import kotlin.time.Duration.Companion.seconds
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -410,12 +414,16 @@
}
@Test
+ @EnableFlags(DevicePolicyFlags.FLAG_HEADLESS_SINGLE_USER_FIXES)
fun upcomingWipe() =
testScope.runTest {
val upcomingWipe by collectLastValue(underTest.upcomingWipe)
kosmos.fakeAuthenticationRepository.setAuthenticationMethod(Pin)
val correctPin = FakeAuthenticationRepository.DEFAULT_PIN
val wrongPin = FakeAuthenticationRepository.DEFAULT_PIN.map { it + 1 }
+ kosmos.fakeUserRepository.asMainUser()
+ kosmos.fakeAuthenticationRepository.profileWithMinFailedUnlockAttemptsForWipe =
+ FakeUserRepository.MAIN_USER_ID
underTest.authenticate(correctPin)
assertThat(upcomingWipe).isNull()
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt
index 497180b..456fb79 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt
@@ -57,6 +57,8 @@
import com.android.systemui.flags.fakeFeatureFlagsClassic
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
+import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
+import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.kosmos.testScope
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.plugins.activityStarter
@@ -586,6 +588,7 @@
ObservableTransitionState.Transition(
fromScene = currentScene,
toScene = targetScene,
+ currentScene = flowOf(targetScene),
progress = progress,
isInitiatedByUserInput = false,
isUserInputOngoing = flowOf(false),
@@ -630,6 +633,7 @@
ObservableTransitionState.Transition(
fromScene = currentScene,
toScene = targetScene,
+ currentScene = flowOf(targetScene),
progress = progress,
isInitiatedByUserInput = false,
isUserInputOngoing = flowOf(false),
@@ -748,6 +752,7 @@
ObservableTransitionState.Transition(
fromScene = CommunalScenes.Communal,
toScene = CommunalScenes.Blank,
+ currentScene = flowOf(CommunalScenes.Blank),
progress = flowOf(0f),
isInitiatedByUserInput = false,
isUserInputOngoing = flowOf(false),
@@ -776,6 +781,7 @@
ObservableTransitionState.Transition(
fromScene = CommunalScenes.Blank,
toScene = CommunalScenes.Communal,
+ currentScene = flowOf(CommunalScenes.Communal),
progress = flowOf(0f),
isInitiatedByUserInput = false,
isUserInputOngoing = flowOf(false),
@@ -795,6 +801,7 @@
ObservableTransitionState.Transition(
fromScene = CommunalScenes.Communal,
toScene = CommunalScenes.Blank,
+ currentScene = flowOf(CommunalScenes.Blank),
progress = flowOf(1.0f),
isInitiatedByUserInput = false,
isUserInputOngoing = flowOf(false),
@@ -1085,6 +1092,78 @@
.isEqualTo(USER_INFO_WORK.id)
}
+ @Test
+ fun showCommunalFromOccluded_enteredOccludedFromHub() =
+ testScope.runTest {
+ kosmos.setCommunalAvailable(true)
+ val showCommunalFromOccluded by collectLastValue(underTest.showCommunalFromOccluded)
+ assertThat(showCommunalFromOccluded).isFalse()
+
+ kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps(
+ from = KeyguardState.GLANCEABLE_HUB,
+ to = KeyguardState.OCCLUDED,
+ testScope
+ )
+
+ assertThat(showCommunalFromOccluded).isTrue()
+ }
+
+ @Test
+ fun showCommunalFromOccluded_enteredOccludedFromLockscreen() =
+ testScope.runTest {
+ kosmos.setCommunalAvailable(true)
+ val showCommunalFromOccluded by collectLastValue(underTest.showCommunalFromOccluded)
+ assertThat(showCommunalFromOccluded).isFalse()
+
+ kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps(
+ from = KeyguardState.LOCKSCREEN,
+ to = KeyguardState.OCCLUDED,
+ testScope
+ )
+
+ assertThat(showCommunalFromOccluded).isFalse()
+ }
+
+ @Test
+ fun showCommunalFromOccluded_communalBecomesUnavailableWhileOccluded() =
+ testScope.runTest {
+ kosmos.setCommunalAvailable(true)
+ val showCommunalFromOccluded by collectLastValue(underTest.showCommunalFromOccluded)
+ assertThat(showCommunalFromOccluded).isFalse()
+
+ kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps(
+ from = KeyguardState.GLANCEABLE_HUB,
+ to = KeyguardState.OCCLUDED,
+ testScope
+ )
+ runCurrent()
+ kosmos.setCommunalAvailable(false)
+
+ assertThat(showCommunalFromOccluded).isFalse()
+ }
+
+ @Test
+ fun showCommunalFromOccluded_showBouncerWhileOccluded() =
+ testScope.runTest {
+ kosmos.setCommunalAvailable(true)
+ val showCommunalFromOccluded by collectLastValue(underTest.showCommunalFromOccluded)
+ assertThat(showCommunalFromOccluded).isFalse()
+
+ kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps(
+ from = KeyguardState.GLANCEABLE_HUB,
+ to = KeyguardState.OCCLUDED,
+ testScope
+ )
+ runCurrent()
+ kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps(
+ from = KeyguardState.OCCLUDED,
+ to = KeyguardState.PRIMARY_BOUNCER,
+ testScope
+ )
+
+ assertThat(showCommunalFromOccluded).isTrue()
+ }
+
private fun smartspaceTimer(id: String, timestamp: Long = 0L): SmartspaceTarget {
val timer = mock(SmartspaceTarget::class.java)
whenever(timer.smartspaceTargetId).thenReturn(id)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/log/CommunalLoggerStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/log/CommunalLoggerStartableTest.kt
index a51315b..def8698 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/log/CommunalLoggerStartableTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/log/CommunalLoggerStartableTest.kt
@@ -31,6 +31,7 @@
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.emptyFlow
+import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
@@ -194,6 +195,7 @@
return ObservableTransitionState.Transition(
fromScene = from,
toScene = to,
+ currentScene = flowOf(to),
progress = emptyFlow(),
isInitiatedByUserInput = true,
isUserInputOngoing = emptyFlow(),
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
index 20beabb..2546f27 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
@@ -41,6 +41,7 @@
import com.android.systemui.biometrics.domain.interactor.displayStateInteractor
import com.android.systemui.bouncer.data.repository.fakeKeyguardBouncerRepository
import com.android.systemui.bouncer.domain.interactor.alternateBouncerInteractor
+import com.android.systemui.concurrency.fakeExecutor
import com.android.systemui.coroutines.FlowValue
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.coroutines.collectValues
@@ -144,6 +145,7 @@
private val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository
private val testScope = kosmos.testScope
private val fakeUserRepository = kosmos.fakeUserRepository
+ private val fakeExecutor = kosmos.fakeExecutor
private lateinit var authStatus: FlowValue<FaceAuthenticationStatus?>
private lateinit var detectStatus: FlowValue<FaceDetectionStatus?>
private lateinit var authRunning: FlowValue<Boolean?>
@@ -220,12 +222,12 @@
testScope.backgroundScope,
testDispatcher,
testDispatcher,
+ fakeExecutor,
sessionTracker,
uiEventLogger,
FaceAuthenticationLogger(logcatLogBuffer("DeviceEntryFaceAuthRepositoryLog")),
biometricSettingsRepository,
deviceEntryFingerprintAuthRepository,
- trustRepository,
keyguardRepository,
powerInteractor,
keyguardInteractor,
@@ -292,6 +294,7 @@
fun faceLockoutStatusIsPropagated() =
testScope.runTest {
initCollectors()
+ fakeExecutor.runAllReady()
verify(faceManager).addLockoutResetCallback(faceLockoutResetCallback.capture())
allPreconditionsToRunFaceAuthAreTrue()
@@ -1177,6 +1180,7 @@
}
private suspend fun TestScope.allPreconditionsToRunFaceAuthAreTrue() {
+ fakeExecutor.runAllReady()
verify(faceManager, atLeastOnce())
.addLockoutResetCallback(faceLockoutResetCallback.capture())
trustRepository.setCurrentUserTrusted(false)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/AuthRippleInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/AuthRippleInteractorTest.kt
index 88ad3f3..3005d0b 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/AuthRippleInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/AuthRippleInteractorTest.kt
@@ -22,7 +22,7 @@
import com.android.systemui.biometrics.data.repository.fingerprintPropertyRepository
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
-import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
+import com.android.systemui.keyguard.shared.model.BiometricUnlockMode
import com.android.systemui.keyguard.shared.model.BiometricUnlockSource
import com.android.systemui.kosmos.testScope
import com.android.systemui.testKosmos
@@ -70,8 +70,10 @@
fun faceUnlocked_showsAuthRipple() =
testScope.runTest {
val showUnlockRipple by collectLastValue(underTest.showUnlockRipple)
- keyguardRepository.setBiometricUnlockSource(BiometricUnlockSource.FACE_SENSOR)
- keyguardRepository.setBiometricUnlockState(BiometricUnlockModel.WAKE_AND_UNLOCK)
+ keyguardRepository.setBiometricUnlockState(
+ BiometricUnlockMode.WAKE_AND_UNLOCK,
+ BiometricUnlockSource.FACE_SENSOR
+ )
assertThat(showUnlockRipple).isEqualTo(BiometricUnlockSource.FACE_SENSOR)
}
@@ -79,8 +81,10 @@
fun fingerprintUnlocked_showsAuthRipple() =
testScope.runTest {
val showUnlockRippleFromBiometricUnlock by collectLastValue(underTest.showUnlockRipple)
- keyguardRepository.setBiometricUnlockSource(BiometricUnlockSource.FINGERPRINT_SENSOR)
- keyguardRepository.setBiometricUnlockState(BiometricUnlockModel.WAKE_AND_UNLOCK)
+ keyguardRepository.setBiometricUnlockState(
+ BiometricUnlockMode.WAKE_AND_UNLOCK,
+ BiometricUnlockSource.FINGERPRINT_SENSOR
+ )
assertThat(showUnlockRippleFromBiometricUnlock)
.isEqualTo(BiometricUnlockSource.FINGERPRINT_SENSOR)
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntrySourceInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntrySourceInteractorTest.kt
index d216fa0..2e4c97b 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntrySourceInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntrySourceInteractorTest.kt
@@ -21,7 +21,7 @@
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
-import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
+import com.android.systemui.keyguard.shared.model.BiometricUnlockMode
import com.android.systemui.keyguard.shared.model.BiometricUnlockSource
import com.android.systemui.kosmos.testScope
import com.android.systemui.testKosmos
@@ -46,8 +46,10 @@
testScope.runTest {
val deviceEntryFromBiometricAuthentication by
collectLastValue(underTest.deviceEntryFromBiometricSource)
- keyguardRepository.setBiometricUnlockSource(BiometricUnlockSource.FACE_SENSOR)
- keyguardRepository.setBiometricUnlockState(BiometricUnlockModel.WAKE_AND_UNLOCK)
+ keyguardRepository.setBiometricUnlockState(
+ BiometricUnlockMode.WAKE_AND_UNLOCK,
+ BiometricUnlockSource.FACE_SENSOR,
+ )
runCurrent()
assertThat(deviceEntryFromBiometricAuthentication)
.isEqualTo(BiometricUnlockSource.FACE_SENSOR)
@@ -57,8 +59,10 @@
fun deviceEntryFromFingerprintUnlock() = runTest {
val deviceEntryFromBiometricAuthentication by
collectLastValue(underTest.deviceEntryFromBiometricSource)
- keyguardRepository.setBiometricUnlockSource(BiometricUnlockSource.FINGERPRINT_SENSOR)
- keyguardRepository.setBiometricUnlockState(BiometricUnlockModel.WAKE_AND_UNLOCK)
+ keyguardRepository.setBiometricUnlockState(
+ BiometricUnlockMode.WAKE_AND_UNLOCK,
+ BiometricUnlockSource.FINGERPRINT_SENSOR,
+ )
runCurrent()
assertThat(deviceEntryFromBiometricAuthentication)
.isEqualTo(BiometricUnlockSource.FINGERPRINT_SENSOR)
@@ -68,9 +72,10 @@
fun noDeviceEntry() = runTest {
val deviceEntryFromBiometricAuthentication by
collectLastValue(underTest.deviceEntryFromBiometricSource)
- keyguardRepository.setBiometricUnlockSource(BiometricUnlockSource.FINGERPRINT_SENSOR)
- // doesn't dismiss keyguard:
- keyguardRepository.setBiometricUnlockState(BiometricUnlockModel.ONLY_WAKE)
+ keyguardRepository.setBiometricUnlockState(
+ BiometricUnlockMode.ONLY_WAKE, // doesn't dismiss keyguard:
+ BiometricUnlockSource.FINGERPRINT_SENSOR,
+ )
runCurrent()
assertThat(deviceEntryFromBiometricAuthentication).isNull()
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt
index 19b80da..f375ec7 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt
@@ -30,6 +30,7 @@
import com.android.systemui.doze.DozeTransitionCallback
import com.android.systemui.doze.DozeTransitionListener
import com.android.systemui.dreams.DreamOverlayCallbackController
+import com.android.systemui.keyguard.shared.model.BiometricUnlockMode
import com.android.systemui.keyguard.shared.model.BiometricUnlockSource
import com.android.systemui.keyguard.shared.model.DozeStateModel
import com.android.systemui.keyguard.shared.model.DozeTransitionModel
@@ -515,11 +516,9 @@
fun biometricUnlockSource() =
testScope.runTest {
val values = mutableListOf<BiometricUnlockSource?>()
- val job = underTest.biometricUnlockSource.onEach(values::add).launchIn(this)
+ val job = underTest.biometricUnlockState.onEach { values.add(it.source) }.launchIn(this)
runCurrent()
- val captor = argumentCaptor<KeyguardUpdateMonitorCallback>()
- verify(keyguardUpdateMonitor).registerCallback(captor.capture())
// An initial, null value should be initially emitted so that flows combined with this
// one
@@ -535,7 +534,10 @@
BiometricSourceType.FINGERPRINT,
)
.onEach { biometricSourceType ->
- captor.value.onBiometricAuthenticated(0, biometricSourceType, false)
+ underTest.setBiometricUnlockState(
+ BiometricUnlockMode.NONE,
+ BiometricUnlockSource.Companion.fromBiometricSourceType(biometricSourceType)
+ )
runCurrent()
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt
index 69a1a0f..0bfcd54 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt
@@ -24,7 +24,7 @@
import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.AnimatorTestRule
import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
+import com.android.systemui.keyguard.shared.model.BiometricUnlockMode
import com.android.systemui.keyguard.shared.model.BiometricUnlockSource
import com.android.systemui.kosmos.testScope
import com.android.systemui.power.data.repository.powerRepository
@@ -89,7 +89,10 @@
// The source and sensor locations are still null, so we should still be using the
// default reveal despite a biometric unlock.
- fakeKeyguardRepository.setBiometricUnlockState(BiometricUnlockModel.WAKE_AND_UNLOCK)
+ fakeKeyguardRepository.setBiometricUnlockState(
+ BiometricUnlockMode.WAKE_AND_UNLOCK,
+ BiometricUnlockSource.FINGERPRINT_SENSOR
+ )
runCurrent()
values.assertEffectsMatchPredicates(
@@ -98,7 +101,10 @@
// We got a source but still have no sensor locations, so should be sticking with
// the default effect.
- fakeKeyguardRepository.setBiometricUnlockSource(BiometricUnlockSource.FINGERPRINT_SENSOR)
+ fakeKeyguardRepository.setBiometricUnlockState(
+ BiometricUnlockMode.WAKE_AND_UNLOCK,
+ BiometricUnlockSource.FINGERPRINT_SENSOR
+ )
runCurrent()
values.assertEffectsMatchPredicates(
@@ -117,8 +123,10 @@
// Now we have fingerprint sensor locations, and wake and unlock via fingerprint.
val fingerprintLocation = Point(500, 500)
fakeKeyguardRepository.setFingerprintSensorLocation(fingerprintLocation)
- fakeKeyguardRepository.setBiometricUnlockSource(BiometricUnlockSource.FINGERPRINT_SENSOR)
- fakeKeyguardRepository.setBiometricUnlockState(BiometricUnlockModel.WAKE_AND_UNLOCK_PULSING)
+ fakeKeyguardRepository.setBiometricUnlockState(
+ BiometricUnlockMode.WAKE_AND_UNLOCK_PULSING,
+ BiometricUnlockSource.FINGERPRINT_SENSOR
+ )
// We should now have switched to the circle reveal, at the fingerprint location.
runCurrent()
@@ -133,14 +141,21 @@
// Subsequent wake and unlocks should not emit duplicate, identical CircleReveals.
val valuesPrevSize = values.size
- fakeKeyguardRepository.setBiometricUnlockState(BiometricUnlockModel.WAKE_AND_UNLOCK_PULSING)
fakeKeyguardRepository.setBiometricUnlockState(
- BiometricUnlockModel.WAKE_AND_UNLOCK_FROM_DREAM
+ BiometricUnlockMode.WAKE_AND_UNLOCK_PULSING,
+ BiometricUnlockSource.FINGERPRINT_SENSOR
+ )
+ fakeKeyguardRepository.setBiometricUnlockState(
+ BiometricUnlockMode.WAKE_AND_UNLOCK_FROM_DREAM,
+ BiometricUnlockSource.FINGERPRINT_SENSOR
)
assertEquals(valuesPrevSize, values.size)
// Non-biometric unlock, we should return to the default reveal.
- fakeKeyguardRepository.setBiometricUnlockState(BiometricUnlockModel.NONE)
+ fakeKeyguardRepository.setBiometricUnlockState(
+ BiometricUnlockMode.NONE,
+ BiometricUnlockSource.FINGERPRINT_SENSOR
+ )
runCurrent()
values.assertEffectsMatchPredicates(
@@ -155,9 +170,10 @@
// We already have a face location, so switching to face source should update the
// CircleReveal.
- fakeKeyguardRepository.setBiometricUnlockSource(BiometricUnlockSource.FACE_SENSOR)
- runCurrent()
- fakeKeyguardRepository.setBiometricUnlockState(BiometricUnlockModel.WAKE_AND_UNLOCK)
+ fakeKeyguardRepository.setBiometricUnlockState(
+ BiometricUnlockMode.WAKE_AND_UNLOCK,
+ BiometricUnlockSource.FACE_SENSOR
+ )
runCurrent()
values.assertEffectsMatchPredicates(
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorTest.kt
index 360f284..d630a2f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorTest.kt
@@ -43,8 +43,7 @@
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
import com.android.systemui.keyguard.data.repository.keyguardOcclusionRepository
-import com.android.systemui.keyguard.data.repository.keyguardRepository
-import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
+import com.android.systemui.keyguard.shared.model.BiometricUnlockMode
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.TransitionStep
@@ -99,7 +98,7 @@
to = KeyguardState.AOD,
testScope
)
- kosmos.keyguardRepository.setBiometricUnlockState(BiometricUnlockModel.NONE)
+ kosmos.fakeKeyguardRepository.setBiometricUnlockState(BiometricUnlockMode.NONE)
reset(transitionRepository)
}
}
@@ -278,7 +277,9 @@
@EnableFlags(Flags.FLAG_KEYGUARD_WM_STATE_REFACTOR)
fun testWakeAndUnlock_transitionsToGone_onlyAfterDismissCallPostWakeup() =
testScope.runTest {
- kosmos.keyguardRepository.setBiometricUnlockState(BiometricUnlockModel.WAKE_AND_UNLOCK)
+ kosmos.fakeKeyguardRepository.setBiometricUnlockState(
+ BiometricUnlockMode.WAKE_AND_UNLOCK
+ )
powerInteractor.setAwakeForTest()
runCurrent()
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt
index 12f8918..cb2d4e0 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt
@@ -24,23 +24,23 @@
import com.android.compose.animation.scene.ObservableTransitionState
import com.android.systemui.Flags.FLAG_KEYGUARD_WM_STATE_REFACTOR
import com.android.systemui.SysuiTestCase
-import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository
-import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
-import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
+import com.android.systemui.bouncer.data.repository.keyguardBouncerRepository
+import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.flags.EnableSceneContainer
-import com.android.systemui.keyguard.data.repository.FakeCommandQueue
+import com.android.systemui.keyguard.data.repository.fakeCommandQueue
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
import com.android.systemui.keyguard.shared.model.CameraLaunchSourceModel
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.StatusBarState
+import com.android.systemui.keyguard.shared.model.TransitionState
+import com.android.systemui.keyguard.shared.model.TransitionStep
import com.android.systemui.kosmos.testScope
-import com.android.systemui.power.domain.interactor.PowerInteractorFactory
+import com.android.systemui.res.R
import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.scene.shared.model.Scenes
-import com.android.systemui.shade.data.repository.FakeShadeRepository
-import com.android.systemui.statusbar.notification.stack.domain.interactor.sharedNotificationContainerInteractor
+import com.android.systemui.shade.data.repository.shadeRepository
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -60,33 +60,17 @@
private val kosmos = testKosmos()
private val testScope = kosmos.testScope
- private val repository by lazy { kosmos.fakeKeyguardRepository }
- private val sceneInteractor by lazy { kosmos.sceneInteractor }
- private val fromGoneTransitionInteractor by lazy { kosmos.fromGoneTransitionInteractor }
- private val commandQueue by lazy { FakeCommandQueue() }
- private val bouncerRepository = FakeKeyguardBouncerRepository()
- private val shadeRepository = FakeShadeRepository()
+ private val repository = kosmos.fakeKeyguardRepository
+ private val sceneInteractor = kosmos.sceneInteractor
+ private val fromGoneTransitionInteractor = kosmos.fromGoneTransitionInteractor
+ private val commandQueue = kosmos.fakeCommandQueue
+ private val configRepository = kosmos.fakeConfigurationRepository
+ private val bouncerRepository = kosmos.keyguardBouncerRepository
+ private val shadeRepository = kosmos.shadeRepository
private val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository
private val transitionState: MutableStateFlow<ObservableTransitionState> =
MutableStateFlow(ObservableTransitionState.Idle(Scenes.Gone))
-
- private val underTest by lazy {
- KeyguardInteractor(
- repository = repository,
- commandQueue = commandQueue,
- powerInteractor = PowerInteractorFactory.create().powerInteractor,
- bouncerRepository = bouncerRepository,
- configurationInteractor = ConfigurationInteractor(FakeConfigurationRepository()),
- shadeRepository = shadeRepository,
- keyguardTransitionInteractor = kosmos.keyguardTransitionInteractor,
- sceneInteractorProvider = { sceneInteractor },
- fromGoneTransitionInteractor = { fromGoneTransitionInteractor },
- sharedNotificationContainerInteractor = {
- kosmos.sharedNotificationContainerInteractor
- },
- applicationScope = testScope,
- )
- }
+ private val underTest = kosmos.keyguardInteractor
@Before
fun setUp() {
@@ -247,6 +231,84 @@
}
@Test
+ fun keyguardTranslationY_whenGoneEmitsZero() =
+ testScope.runTest {
+ val keyguardTranslationY by collectLastValue(underTest.keyguardTranslationY)
+
+ configRepository.setDimensionPixelSize(
+ R.dimen.keyguard_translate_distance_on_swipe_up,
+ 100
+ )
+ configRepository.onAnyConfigurationChange()
+
+ shadeRepository.setLegacyShadeExpansion(0f)
+
+ keyguardTransitionRepository.sendTransitionSteps(
+ from = KeyguardState.AOD,
+ to = KeyguardState.GONE,
+ testScope,
+ )
+
+ assertThat(keyguardTranslationY).isEqualTo(0f)
+ }
+
+ @Test
+ fun keyguardTranslationY_whenNotGoneAndShadeIsFullyCollapsedEmitsZero() =
+ testScope.runTest {
+ val keyguardTranslationY by collectLastValue(underTest.keyguardTranslationY)
+
+ configRepository.setDimensionPixelSize(
+ R.dimen.keyguard_translate_distance_on_swipe_up,
+ 100
+ )
+ configRepository.onAnyConfigurationChange()
+
+ shadeRepository.setLegacyShadeExpansion(0f)
+
+ keyguardTransitionRepository.sendTransitionSteps(
+ from = KeyguardState.AOD,
+ to = KeyguardState.LOCKSCREEN,
+ testScope,
+ )
+
+ assertThat(keyguardTranslationY).isEqualTo(0f)
+ }
+
+ @Test
+ fun keyguardTranslationY_whenTransitioningToGoneAndShadeIsExpandingEmitsNonZero() =
+ testScope.runTest {
+ val keyguardTranslationY by collectLastValue(underTest.keyguardTranslationY)
+
+ configRepository.setDimensionPixelSize(
+ R.dimen.keyguard_translate_distance_on_swipe_up,
+ 100
+ )
+ configRepository.onAnyConfigurationChange()
+
+ shadeRepository.setLegacyShadeExpansion(0.5f)
+
+ keyguardTransitionRepository.sendTransitionSteps(
+ listOf(
+ TransitionStep(
+ from = KeyguardState.AOD,
+ to = KeyguardState.GONE,
+ value = 0f,
+ transitionState = TransitionState.STARTED,
+ ),
+ TransitionStep(
+ from = KeyguardState.AOD,
+ to = KeyguardState.GONE,
+ value = 0.1f,
+ transitionState = TransitionState.RUNNING,
+ ),
+ ),
+ testScope,
+ )
+
+ assertThat(keyguardTranslationY).isGreaterThan(0f)
+ }
+
+ @Test
@EnableSceneContainer
fun animationDozingTransitions() =
testScope.runTest {
@@ -265,6 +327,7 @@
ObservableTransitionState.Transition(
fromScene = Scenes.Gone,
toScene = Scenes.Lockscreen,
+ currentScene = flowOf(Scenes.Lockscreen),
progress = flowOf(0f),
isInitiatedByUserInput = false,
isUserInputOngoing = flowOf(false),
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt
index 41229255..bf0939c 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt
@@ -235,7 +235,13 @@
.isEqualTo(
listOf(
// The initial transition will also get sent when collect started
- TransitionStep(OFF, LOCKSCREEN, 0f, STARTED),
+ TransitionStep(
+ OFF,
+ LOCKSCREEN,
+ 0f,
+ STARTED,
+ ownerName = "KeyguardTransitionRepository(boot)"
+ ),
steps[0],
steps[3],
steps[6]
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToGoneTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToGoneTransitionViewModelTest.kt
index 5bf0f4b..692ffee 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToGoneTransitionViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToGoneTransitionViewModelTest.kt
@@ -36,7 +36,6 @@
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
-import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -54,11 +53,6 @@
private val sysuiStatusBarStateController = kosmos.sysuiStatusBarStateController
private val underTest by lazy { kosmos.alternateBouncerToGoneTransitionViewModel }
- @Before
- fun setup() {
- mSetFlagsRule.disableFlags(com.android.systemui.Flags.FLAG_REFACTOR_KEYGUARD_DISMISS_INTENT)
- }
-
@Test
fun deviceEntryParentViewDisappear() =
testScope.runTest {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToPrimaryBouncerTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToPrimaryBouncerTransitionViewModelTest.kt
index 854a478..9fab603 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToPrimaryBouncerTransitionViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToPrimaryBouncerTransitionViewModelTest.kt
@@ -32,7 +32,6 @@
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
-import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -48,11 +47,6 @@
private val keyguardTransitionRepository by lazy { kosmos.fakeKeyguardTransitionRepository }
private val underTest by lazy { kosmos.alternateBouncerToPrimaryBouncerTransitionViewModel }
- @Before
- fun setup() {
- mSetFlagsRule.disableFlags(com.android.systemui.Flags.FLAG_REFACTOR_KEYGUARD_DISMISS_INTENT)
- }
-
@Test
fun deviceEntryParentViewDisappear() =
testScope.runTest {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AodToLockscreenTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AodToLockscreenTransitionViewModelTest.kt
index 31b67b4..f52c66e 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AodToLockscreenTransitionViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AodToLockscreenTransitionViewModelTest.kt
@@ -16,36 +16,57 @@
package com.android.systemui.keyguard.ui.viewmodel
-import androidx.test.ext.junit.runners.AndroidJUnit4
+import android.platform.test.flag.junit.FlagsParameterization
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.biometrics.data.repository.fingerprintPropertyRepository
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.coroutines.collectValues
+import com.android.systemui.flags.andSceneContainer
import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.TransitionStep
import com.android.systemui.kosmos.testScope
-import com.android.systemui.shade.data.repository.fakeShadeRepository
+import com.android.systemui.shade.shadeTestUtil
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
+import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4
+import platform.test.runner.parameterized.Parameters
@ExperimentalCoroutinesApi
@SmallTest
-@RunWith(AndroidJUnit4::class)
-class AodToLockscreenTransitionViewModelTest : SysuiTestCase() {
+@RunWith(ParameterizedAndroidJunit4::class)
+class AodToLockscreenTransitionViewModelTest(flags: FlagsParameterization?) : SysuiTestCase() {
val kosmos = testKosmos()
val testScope = kosmos.testScope
val repository = kosmos.fakeKeyguardTransitionRepository
- val shadeRepository = kosmos.fakeShadeRepository
+ val shadeTestUtil by lazy { kosmos.shadeTestUtil }
val fingerprintPropertyRepository = kosmos.fingerprintPropertyRepository
- val underTest = kosmos.aodToLockscreenTransitionViewModel
+ lateinit var underTest: AodToLockscreenTransitionViewModel
+
+ companion object {
+ @JvmStatic
+ @Parameters(name = "{0}")
+ fun getParams(): List<FlagsParameterization> {
+ return FlagsParameterization.allCombinationsOf().andSceneContainer()
+ }
+ }
+
+ init {
+ mSetFlagsRule.setFlagsParameterization(flags!!)
+ }
+
+ @Before
+ fun setup() {
+ underTest = kosmos.aodToLockscreenTransitionViewModel
+ }
@Test
fun deviceEntryParentViewShows() =
@@ -65,7 +86,7 @@
testScope.runTest {
val alpha by collectLastValue(underTest.notificationAlpha)
- shadeRepository.setQsExpansion(0.5f)
+ shadeTestUtil.setQsExpansion(0.5f)
runCurrent()
repository.sendTransitionStep(step(0f, TransitionState.STARTED))
@@ -81,7 +102,7 @@
testScope.runTest {
val alpha by collectLastValue(underTest.notificationAlpha)
- shadeRepository.setQsExpansion(0f)
+ shadeTestUtil.setQsExpansion(0f)
runCurrent()
repository.sendTransitionStep(step(0f, TransitionState.STARTED))
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlowsTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlowsTest.kt
index ee217a6..fee18dd 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlowsTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlowsTest.kt
@@ -69,7 +69,6 @@
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
- mSetFlagsRule.disableFlags(com.android.systemui.Flags.FLAG_REFACTOR_KEYGUARD_DISMISS_INTENT)
whenever(primaryBouncerInteractor.willRunDismissFromKeyguard()).thenReturn(false)
sysuiStatusBarStateController.setLeaveOpenOnKeyguardHide(false)
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt
index 030aa24..2e1765a 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt
@@ -23,6 +23,7 @@
import android.view.View
import androidx.test.filters.SmallTest
import com.android.compose.animation.scene.ObservableTransitionState
+import com.android.systemui.Flags as AConfigFlags
import com.android.systemui.Flags.FLAG_NEW_AOD_TRANSITION
import com.android.systemui.SysuiTestCase
import com.android.systemui.communal.data.repository.communalRepository
@@ -56,7 +57,6 @@
import org.junit.runner.RunWith
import platform.test.runner.parameterized.ParameterizedAndroidJunit4
import platform.test.runner.parameterized.Parameters
-import com.android.systemui.Flags as AConfigFlags
@SmallTest
@RunWith(ParameterizedAndroidJunit4::class)
@@ -95,7 +95,6 @@
mSetFlagsRule.enableFlags(AConfigFlags.FLAG_KEYGUARD_BOTTOM_AREA_REFACTOR)
mSetFlagsRule.disableFlags(
AConfigFlags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT,
- AConfigFlags.FLAG_REFACTOR_KEYGUARD_DISMISS_INTENT,
)
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToAodTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToAodTransitionViewModelTest.kt
index bef9515..e3ae3ba 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToAodTransitionViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToAodTransitionViewModelTest.kt
@@ -16,13 +16,14 @@
package com.android.systemui.keyguard.ui.viewmodel
-import androidx.test.ext.junit.runners.AndroidJUnit4
+import android.platform.test.flag.junit.FlagsParameterization
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.biometrics.data.repository.fingerprintPropertyRepository
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.coroutines.collectValues
import com.android.systemui.flags.Flags.FULL_SCREEN_USER_SWITCHER
+import com.android.systemui.flags.andSceneContainer
import com.android.systemui.flags.fakeFeatureFlagsClassic
import com.android.systemui.keyguard.data.repository.biometricSettingsRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
@@ -32,31 +33,53 @@
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.TransitionStep
import com.android.systemui.kosmos.testScope
-import com.android.systemui.shade.data.repository.shadeRepository
+import com.android.systemui.shade.shadeTestUtil
import com.android.systemui.testKosmos
import com.google.common.collect.Range
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
+import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4
+import platform.test.runner.parameterized.Parameters
@ExperimentalCoroutinesApi
@SmallTest
-@RunWith(AndroidJUnit4::class)
-class LockscreenToAodTransitionViewModelTest : SysuiTestCase() {
+@RunWith(ParameterizedAndroidJunit4::class)
+class LockscreenToAodTransitionViewModelTest(flags: FlagsParameterization?) : SysuiTestCase() {
private val kosmos =
testKosmos().apply {
fakeFeatureFlagsClassic.apply { set(FULL_SCREEN_USER_SWITCHER, false) }
}
private val testScope = kosmos.testScope
private val repository = kosmos.fakeKeyguardTransitionRepository
- private val shadeRepository = kosmos.shadeRepository
private val keyguardRepository = kosmos.fakeKeyguardRepository
private val fingerprintPropertyRepository = kosmos.fingerprintPropertyRepository
private val biometricSettingsRepository = kosmos.biometricSettingsRepository
- private val underTest = kosmos.lockscreenToAodTransitionViewModel
+
+ private val shadeTestUtil by lazy { kosmos.shadeTestUtil }
+
+ lateinit var underTest: LockscreenToAodTransitionViewModel
+
+ companion object {
+ @JvmStatic
+ @Parameters(name = "{0}")
+ fun getParams(): List<FlagsParameterization> {
+ return FlagsParameterization.allCombinationsOf().andSceneContainer()
+ }
+ }
+
+ init {
+ mSetFlagsRule.setFlagsParameterization(flags!!)
+ }
+
+ @Before
+ fun setup() {
+ underTest = kosmos.lockscreenToAodTransitionViewModel
+ }
@Test
fun backgroundViewAlpha_shadeNotExpanded() =
@@ -195,11 +218,11 @@
private fun shadeExpanded(expanded: Boolean) {
if (expanded) {
- shadeRepository.setQsExpansion(1f)
+ shadeTestUtil.setQsExpansion(1f)
} else {
keyguardRepository.setStatusBarState(StatusBarState.KEYGUARD)
- shadeRepository.setQsExpansion(0f)
- shadeRepository.setLockscreenShadeExpansion(0f)
+ shadeTestUtil.setQsExpansion(0f)
+ shadeTestUtil.setLockscreenShadeExpansion(0f)
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelTest.kt
index 8f04ec38..adeb395 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelTest.kt
@@ -18,24 +18,25 @@
package com.android.systemui.keyguard.ui.viewmodel
-import androidx.test.ext.junit.runners.AndroidJUnit4
+import android.platform.test.flag.junit.FlagsParameterization
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.coroutines.collectValues
import com.android.systemui.flags.Flags
+import com.android.systemui.flags.andSceneContainer
import com.android.systemui.flags.fakeFeatureFlagsClassic
-import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
-import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
+import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
+import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.StatusBarState
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.TransitionStep
import com.android.systemui.kosmos.testScope
-import com.android.systemui.shade.data.repository.shadeRepository
-import com.android.systemui.shade.data.repository.ShadeRepository
+import com.android.systemui.shade.ShadeTestUtil
+import com.android.systemui.shade.shadeTestUtil
import com.android.systemui.testKosmos
import com.google.common.collect.Range
import com.google.common.truth.Truth.assertThat
@@ -45,10 +46,12 @@
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4
+import platform.test.runner.parameterized.Parameters
@SmallTest
-@RunWith(AndroidJUnit4::class)
-class LockscreenToDreamingTransitionViewModelTest : SysuiTestCase() {
+@RunWith(ParameterizedAndroidJunit4::class)
+class LockscreenToDreamingTransitionViewModelTest(flags: FlagsParameterization?) : SysuiTestCase() {
private val kosmos =
testKosmos().apply {
@@ -56,14 +59,27 @@
}
private val testScope = kosmos.testScope
private lateinit var repository: FakeKeyguardTransitionRepository
- private lateinit var shadeRepository: ShadeRepository
+ private lateinit var shadeTestUtil: ShadeTestUtil
private lateinit var keyguardRepository: FakeKeyguardRepository
private lateinit var underTest: LockscreenToDreamingTransitionViewModel
+ // add to init block
+ companion object {
+ @JvmStatic
+ @Parameters(name = "{0}")
+ fun getParams(): List<FlagsParameterization> {
+ return FlagsParameterization.allCombinationsOf().andSceneContainer()
+ }
+ }
+
+ init {
+ mSetFlagsRule.setFlagsParameterization(flags!!)
+ }
+
@Before
fun setUp() {
repository = kosmos.fakeKeyguardTransitionRepository
- shadeRepository = kosmos.shadeRepository
+ shadeTestUtil = kosmos.shadeTestUtil
keyguardRepository = kosmos.fakeKeyguardRepository
underTest = kosmos.lockscreenToDreamingTransitionViewModel
}
@@ -177,11 +193,11 @@
private fun shadeExpanded(expanded: Boolean) {
if (expanded) {
- shadeRepository.setQsExpansion(1f)
+ shadeTestUtil.setQsExpansion(1f)
} else {
keyguardRepository.setStatusBarState(StatusBarState.KEYGUARD)
- shadeRepository.setQsExpansion(0f)
- shadeRepository.setLockscreenShadeExpansion(0f)
+ shadeTestUtil.setQsExpansion(0f)
+ shadeTestUtil.setLockscreenShadeExpansion(0f)
}
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelTest.kt
index b120f87..f8da74f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelTest.kt
@@ -18,27 +18,28 @@
package com.android.systemui.keyguard.ui.viewmodel
-import androidx.test.ext.junit.runners.AndroidJUnit4
+import android.platform.test.flag.junit.FlagsParameterization
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
-import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
+import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.coroutines.collectValues
import com.android.systemui.flags.Flags
+import com.android.systemui.flags.andSceneContainer
import com.android.systemui.flags.fakeFeatureFlagsClassic
-import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
-import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
+import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
+import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.StatusBarState
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.TransitionStep
import com.android.systemui.kosmos.testScope
import com.android.systemui.res.R
-import com.android.systemui.shade.data.repository.shadeRepository
-import com.android.systemui.shade.data.repository.ShadeRepository
+import com.android.systemui.shade.ShadeTestUtil
+import com.android.systemui.shade.shadeTestUtil
import com.android.systemui.testKosmos
import com.google.common.collect.Range
import com.google.common.truth.Truth.assertThat
@@ -48,25 +49,40 @@
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4
+import platform.test.runner.parameterized.Parameters
@SmallTest
-@RunWith(AndroidJUnit4::class)
-class LockscreenToOccludedTransitionViewModelTest : SysuiTestCase() {
+@RunWith(ParameterizedAndroidJunit4::class)
+class LockscreenToOccludedTransitionViewModelTest(flags: FlagsParameterization?) : SysuiTestCase() {
private val kosmos =
testKosmos().apply {
fakeFeatureFlagsClassic.apply { set(Flags.FULL_SCREEN_USER_SWITCHER, false) }
}
private val testScope = kosmos.testScope
private lateinit var repository: FakeKeyguardTransitionRepository
- private lateinit var shadeRepository: ShadeRepository
+ private lateinit var shadeTestUtil: ShadeTestUtil
private lateinit var keyguardRepository: FakeKeyguardRepository
private lateinit var configurationRepository: FakeConfigurationRepository
private lateinit var underTest: LockscreenToOccludedTransitionViewModel
+ // add to init block
+ companion object {
+ @JvmStatic
+ @Parameters(name = "{0}")
+ fun getParams(): List<FlagsParameterization> {
+ return FlagsParameterization.allCombinationsOf().andSceneContainer()
+ }
+ }
+
+ init {
+ mSetFlagsRule.setFlagsParameterization(flags!!)
+ }
+
@Before
fun setUp() {
repository = kosmos.fakeKeyguardTransitionRepository
- shadeRepository = kosmos.shadeRepository
+ shadeTestUtil = kosmos.shadeTestUtil
keyguardRepository = kosmos.fakeKeyguardRepository
configurationRepository = kosmos.fakeConfigurationRepository
underTest = kosmos.lockscreenToOccludedTransitionViewModel
@@ -200,11 +216,11 @@
private fun shadeExpanded(expanded: Boolean) {
if (expanded) {
- shadeRepository.setQsExpansion(1f)
+ shadeTestUtil.setQsExpansion(1f)
} else {
keyguardRepository.setStatusBarState(StatusBarState.KEYGUARD)
- shadeRepository.setQsExpansion(0f)
- shadeRepository.setLockscreenShadeExpansion(0f)
+ shadeTestUtil.setQsExpansion(0f)
+ shadeTestUtil.setLockscreenShadeExpansion(0f)
}
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModelTest.kt
index 43ab93a..d5df159 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModelTest.kt
@@ -16,11 +16,12 @@
package com.android.systemui.keyguard.ui.viewmodel
-import androidx.test.ext.junit.runners.AndroidJUnit4
+import android.platform.test.flag.junit.FlagsParameterization
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.flags.Flags
+import com.android.systemui.flags.andSceneContainer
import com.android.systemui.flags.fakeFeatureFlagsClassic
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
@@ -29,29 +30,50 @@
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.TransitionStep
import com.android.systemui.kosmos.testScope
-import com.android.systemui.shade.data.repository.shadeRepository
+import com.android.systemui.shade.shadeTestUtil
import com.android.systemui.testKosmos
import com.google.common.collect.Range
import com.google.common.truth.Truth
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
+import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4
+import platform.test.runner.parameterized.Parameters
@ExperimentalCoroutinesApi
@SmallTest
-@RunWith(AndroidJUnit4::class)
-class LockscreenToPrimaryBouncerTransitionViewModelTest : SysuiTestCase() {
+@RunWith(ParameterizedAndroidJunit4::class)
+class LockscreenToPrimaryBouncerTransitionViewModelTest(flags: FlagsParameterization?) :
+ SysuiTestCase() {
private val kosmos =
testKosmos().apply {
fakeFeatureFlagsClassic.apply { set(Flags.FULL_SCREEN_USER_SWITCHER, false) }
}
private val testScope = kosmos.testScope
private val repository = kosmos.fakeKeyguardTransitionRepository
- private val shadeRepository = kosmos.shadeRepository
+ private val shadeTestUtil by lazy { kosmos.shadeTestUtil }
private val keyguardRepository = kosmos.fakeKeyguardRepository
- private val underTest = kosmos.lockscreenToPrimaryBouncerTransitionViewModel
+ private lateinit var underTest: LockscreenToPrimaryBouncerTransitionViewModel
+
+ companion object {
+ @JvmStatic
+ @Parameters(name = "{0}")
+ fun getParams(): List<FlagsParameterization> {
+ return FlagsParameterization.allCombinationsOf().andSceneContainer()
+ }
+ }
+
+ init {
+ mSetFlagsRule.setFlagsParameterization(flags!!)
+ }
+
+ @Before
+ fun setup() {
+ underTest = kosmos.lockscreenToPrimaryBouncerTransitionViewModel
+ }
@Test
fun deviceEntryParentViewAlpha_shadeExpanded() =
@@ -119,11 +141,11 @@
private fun shadeExpanded(expanded: Boolean) {
if (expanded) {
- shadeRepository.setQsExpansion(1f)
+ shadeTestUtil.setQsExpansion(1f)
} else {
keyguardRepository.setStatusBarState(StatusBarState.KEYGUARD)
- shadeRepository.setQsExpansion(0f)
- shadeRepository.setLockscreenShadeExpansion(0f)
+ shadeTestUtil.setQsExpansion(0f)
+ shadeTestUtil.setLockscreenShadeExpansion(0f)
}
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt
index 18e9009..278c90a 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt
@@ -55,7 +55,6 @@
@Before
fun setUp() {
- mSetFlagsRule.disableFlags(com.android.systemui.Flags.FLAG_REFACTOR_KEYGUARD_DISMISS_INTENT)
whenever(primaryBouncerInteractor.willRunDismissFromKeyguard()).thenReturn(false)
sysuiStatusBarStateController.setLeaveOpenOnKeyguardHide(false)
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeSceneViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeSceneViewModelTest.kt
new file mode 100644
index 0000000..5661bd3
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeSceneViewModelTest.kt
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.notifications.ui.viewmodel
+
+import android.testing.TestableLooper
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.compose.animation.scene.Swipe
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository
+import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.deviceentry.data.repository.fakeDeviceEntryRepository
+import com.android.systemui.deviceentry.domain.interactor.deviceUnlockedInteractor
+import com.android.systemui.flags.EnableSceneContainer
+import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository
+import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.scene.domain.interactor.sceneInteractor
+import com.android.systemui.scene.shared.model.Scenes
+import com.android.systemui.shade.ui.viewmodel.notificationsShadeSceneViewModel
+import com.android.systemui.testKosmos
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+@TestableLooper.RunWithLooper
+@EnableSceneContainer
+class NotificationsShadeSceneViewModelTest : SysuiTestCase() {
+
+ private val kosmos = testKosmos()
+ private val testScope = kosmos.testScope
+ private val sceneInteractor = kosmos.sceneInteractor
+ private val deviceUnlockedInteractor = kosmos.deviceUnlockedInteractor
+
+ private val underTest = kosmos.notificationsShadeSceneViewModel
+
+ @Test
+ fun upTransitionSceneKey_deviceLocked_lockscreen() =
+ testScope.runTest {
+ val destinationScenes by collectLastValue(underTest.destinationScenes)
+ lockDevice()
+
+ assertThat(destinationScenes?.get(Swipe.Up)?.toScene).isEqualTo(Scenes.Lockscreen)
+ }
+
+ @Test
+ fun upTransitionSceneKey_deviceUnlocked_gone() =
+ testScope.runTest {
+ val destinationScenes by collectLastValue(underTest.destinationScenes)
+ lockDevice()
+ unlockDevice()
+
+ assertThat(destinationScenes?.get(Swipe.Up)?.toScene).isEqualTo(Scenes.Gone)
+ }
+
+ @Test
+ fun upTransitionSceneKey_authMethodSwipe_lockscreenNotDismissed_goesToLockscreen() =
+ testScope.runTest {
+ val destinationScenes by collectLastValue(underTest.destinationScenes)
+ kosmos.fakeDeviceEntryRepository.setLockscreenEnabled(true)
+ kosmos.fakeAuthenticationRepository.setAuthenticationMethod(
+ AuthenticationMethodModel.None
+ )
+ sceneInteractor.changeScene(Scenes.Lockscreen, "reason")
+
+ assertThat(destinationScenes?.get(Swipe.Up)?.toScene).isEqualTo(Scenes.Lockscreen)
+ }
+
+ @Test
+ fun upTransitionSceneKey_authMethodSwipe_lockscreenDismissed_goesToGone() =
+ testScope.runTest {
+ val destinationScenes by collectLastValue(underTest.destinationScenes)
+ kosmos.fakeDeviceEntryRepository.setLockscreenEnabled(true)
+ kosmos.fakeAuthenticationRepository.setAuthenticationMethod(
+ AuthenticationMethodModel.None
+ )
+ runCurrent()
+ sceneInteractor.changeScene(Scenes.Gone, "reason")
+
+ assertThat(destinationScenes?.get(Swipe.Up)?.toScene).isEqualTo(Scenes.Gone)
+ }
+
+ private fun TestScope.lockDevice() {
+ val deviceUnlockStatus by collectLastValue(deviceUnlockedInteractor.deviceUnlockStatus)
+
+ kosmos.fakeAuthenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
+ assertThat(deviceUnlockStatus?.isUnlocked).isFalse()
+ sceneInteractor.changeScene(Scenes.Lockscreen, "reason")
+ runCurrent()
+ }
+
+ private fun TestScope.unlockDevice() {
+ val deviceUnlockStatus by collectLastValue(deviceUnlockedInteractor.deviceUnlockStatus)
+
+ kosmos.fakeDeviceEntryFingerprintAuthRepository.setAuthenticationStatus(
+ SuccessFingerprintAuthenticationStatus(0, true)
+ )
+ assertThat(deviceUnlockStatus?.isUnlocked).isTrue()
+ sceneInteractor.changeScene(Scenes.Gone, "reason")
+ runCurrent()
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/data/repository/InstalledTilesComponentRepositoryImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/data/repository/InstalledTilesComponentRepositoryImplTest.kt
index 9c0674d..bc57ce6 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/data/repository/InstalledTilesComponentRepositoryImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/data/repository/InstalledTilesComponentRepositoryImplTest.kt
@@ -245,6 +245,33 @@
assertThat(flowForUser2).isNotEqualTo(flowForUser1)
}
+ // Tests that a ServiceInfo that is returned by queryIntentServicesAsUser but shortly
+ // after uninstalled, doesn't crash SystemUI.
+ @Test
+ fun packageUninstalledAfterQuery_noCrash_noComponent() =
+ testScope.runTest {
+ val userId = 0
+ val resolveInfo =
+ ResolveInfo(TEST_COMPONENT, hasPermission = true, defaultEnabled = true)
+
+ val componentNames by collectLastValue(underTest.getInstalledTilesComponents(userId))
+
+ whenever(
+ packageManager.queryIntentServicesAsUser(
+ matchIntent(),
+ matchFlags(),
+ eq(userId)
+ )
+ )
+ .thenReturn(listOf(resolveInfo))
+ whenever(packageManager.getComponentEnabledSetting(TEST_COMPONENT))
+ .thenThrow(IllegalArgumentException())
+ kosmos.fakePackageChangeRepository.notifyChange(PackageChangeModel.Empty)
+ runCurrent()
+
+ assertThat(componentNames).isEmpty()
+ }
+
companion object {
private val INTENT = Intent(TileService.ACTION_QS_TILE)
private val FLAGS =
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/interactor/FakeQSTile.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/interactor/FakeQSTile.kt
index 7e0e7d1..302ac35 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/interactor/FakeQSTile.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/interactor/FakeQSTile.kt
@@ -16,8 +16,8 @@
package com.android.systemui.qs.pipeline.domain.interactor
-import android.view.View
import com.android.internal.logging.InstanceId
+import com.android.systemui.animation.Expandable
import com.android.systemui.plugins.qs.QSTile
class FakeQSTile(
@@ -56,11 +56,11 @@
callbacks.clear()
}
- override fun click(view: View?) {}
+ override fun click(expandable: Expandable?) {}
- override fun secondaryClick(view: View?) {}
+ override fun secondaryClick(expandable: Expandable?) {}
- override fun longClick(view: View?) {}
+ override fun longClick(expandable: Expandable?) {}
override fun userSwitch(currentUser: Int) {
user = currentUser
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/fontscaling/domain/interactor/FontScalingUserActionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/fontscaling/domain/interactor/FontScalingUserActionInteractorTest.kt
index 182a604..d309554 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/fontscaling/domain/interactor/FontScalingUserActionInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/fontscaling/domain/interactor/FontScalingUserActionInteractorTest.kt
@@ -16,6 +16,7 @@
package com.android.systemui.qs.tiles.impl.fontscaling.domain.interactor
+import android.content.Context
import android.provider.Settings
import android.view.View
import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -23,6 +24,8 @@
import com.android.systemui.SysuiTestCase
import com.android.systemui.accessibility.fontscaling.FontScalingDialogDelegate
import com.android.systemui.animation.DialogTransitionAnimator
+import com.android.systemui.animation.Expandable
+import com.android.systemui.animation.LaunchableView
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.testScope
import com.android.systemui.plugins.ActivityStarter
@@ -36,7 +39,6 @@
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.mockito.mock
-import com.android.systemui.util.mockito.nullable
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth
import kotlinx.coroutines.test.runTest
@@ -63,6 +65,8 @@
@Mock private lateinit var mDialogTransitionAnimator: DialogTransitionAnimator
@Mock private lateinit var dialog: SystemUIDialog
@Mock private lateinit var activityStarter: ActivityStarter
+ @Mock private lateinit var expandable: Expandable
+ @Mock private lateinit var controller: DialogTransitionAnimator.Controller
@Captor private lateinit var argumentCaptor: ArgumentCaptor<Runnable>
@@ -73,6 +77,9 @@
dialog = mock<SystemUIDialog>()
fontScalingDialogDelegate =
mock<FontScalingDialogDelegate> { whenever(createDialog()).thenReturn(dialog) }
+ controller = mock<DialogTransitionAnimator.Controller>()
+ expandable =
+ mock<Expandable> { whenever(dialogTransitionController(any())).thenReturn(controller) }
argumentCaptor = ArgumentCaptor.forClass(Runnable::class.java)
underTest =
@@ -90,9 +97,8 @@
fun clickTile_screenUnlocked_showDialogAnimationFromView() =
kosmos.testScope.runTest {
keyguardStateController.isShowing = false
- val testView = View(context)
- underTest.handleInput(click(FontScalingTileModel, view = testView))
+ underTest.handleInput(click(FontScalingTileModel, expandable = expandable))
verify(activityStarter)
.executeRunnableDismissingKeyguard(
@@ -103,17 +109,15 @@
eq(false)
)
argumentCaptor.value.run()
- verify(mDialogTransitionAnimator)
- .showFromView(any(), eq(testView), nullable(), anyBoolean())
+ verify(mDialogTransitionAnimator).show(any(), any(), anyBoolean())
}
@Test
fun clickTile_onLockScreen_neverShowDialogAnimationFromView_butShowsDialog() =
kosmos.testScope.runTest {
keyguardStateController.isShowing = true
- val testView = View(context)
- underTest.handleInput(click(FontScalingTileModel, view = testView))
+ underTest.handleInput(click(FontScalingTileModel, expandable = expandable))
verify(activityStarter)
.executeRunnableDismissingKeyguard(
@@ -124,8 +128,7 @@
eq(false)
)
argumentCaptor.value.run()
- verify(mDialogTransitionAnimator, never())
- .showFromView(any(), eq(testView), nullable(), anyBoolean())
+ verify(mDialogTransitionAnimator, never()).show(any(), any(), anyBoolean())
verify(dialog).show()
}
@@ -140,4 +143,8 @@
val expectedIntentAction = Settings.ACTION_TEXT_READING_SETTINGS
Truth.assertThat(actualIntentAction).isEqualTo(expectedIntentAction)
}
+
+ private class FontScalingTileTestView(context: Context) : View(context), LaunchableView {
+ override fun setShouldBlockVisibilityChanges(block: Boolean) {}
+ }
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/onehanded/domain/interactor/OneHandedModeTileDataInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/onehanded/domain/interactor/OneHandedModeTileDataInteractorTest.kt
new file mode 100644
index 0000000..0761ee7
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/onehanded/domain/interactor/OneHandedModeTileDataInteractorTest.kt
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.onehanded.domain.interactor
+
+import android.os.UserHandle
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.accessibility.data.repository.oneHandedModeRepository
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.qs.tiles.base.interactor.DataUpdateTrigger
+import com.android.systemui.qs.tiles.impl.onehanded.domain.OneHandedModeTileDataInteractor
+import com.android.wm.shell.onehanded.OneHanded
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class OneHandedModeTileDataInteractorTest : SysuiTestCase() {
+
+ private val kosmos = Kosmos()
+ private val testUser = UserHandle.of(1)!!
+ private val oneHandedModeRepository = kosmos.oneHandedModeRepository
+ private val underTest: OneHandedModeTileDataInteractor =
+ OneHandedModeTileDataInteractor(oneHandedModeRepository)
+
+ @Test
+ fun availability_matchesController() = runTest {
+ val expectedAvailability = OneHanded.sIsSupportOneHandedMode
+ val availability by collectLastValue(underTest.availability(testUser))
+
+ assertThat(availability).isEqualTo(expectedAvailability)
+ }
+
+ @Test
+ fun data_matchesRepository() = runTest {
+ val lastData by
+ collectLastValue(underTest.tileData(testUser, flowOf(DataUpdateTrigger.InitialRequest)))
+ runCurrent()
+ assertThat(lastData!!.isEnabled).isFalse()
+
+ oneHandedModeRepository.setIsEnabled(true, testUser)
+ runCurrent()
+ assertThat(lastData!!.isEnabled).isTrue()
+
+ oneHandedModeRepository.setIsEnabled(false, testUser)
+ runCurrent()
+ assertThat(lastData!!.isEnabled).isFalse()
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/onehanded/domain/interactor/OneHandedModeTileUserActionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/onehanded/domain/interactor/OneHandedModeTileUserActionInteractorTest.kt
new file mode 100644
index 0000000..3f17d4c
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/onehanded/domain/interactor/OneHandedModeTileUserActionInteractorTest.kt
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.onehanded.domain.interactor
+
+import android.os.UserHandle
+import android.platform.test.annotations.EnabledOnRavenwood
+import android.provider.Settings
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.accessibility.data.repository.FakeOneHandedModeRepository
+import com.android.systemui.qs.tiles.base.actions.FakeQSTileIntentUserInputHandler
+import com.android.systemui.qs.tiles.base.actions.QSTileIntentUserInputHandlerSubject
+import com.android.systemui.qs.tiles.base.interactor.QSTileInputTestKtx
+import com.android.systemui.qs.tiles.impl.onehanded.domain.OneHandedModeTileUserActionInteractor
+import com.android.systemui.qs.tiles.impl.onehanded.domain.model.OneHandedModeTileModel
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@EnabledOnRavenwood
+@RunWith(AndroidJUnit4::class)
+class OneHandedModeTileUserActionInteractorTest : SysuiTestCase() {
+
+ private val testUser = UserHandle.of(1)
+ private val repository = FakeOneHandedModeRepository()
+ private val inputHandler = FakeQSTileIntentUserInputHandler()
+
+ private val underTest =
+ OneHandedModeTileUserActionInteractor(
+ repository,
+ inputHandler,
+ )
+
+ @Test
+ fun handleClickWhenEnabled() = runTest {
+ val wasEnabled = true
+ repository.setIsEnabled(wasEnabled, testUser)
+
+ underTest.handleInput(
+ QSTileInputTestKtx.click(OneHandedModeTileModel(wasEnabled), testUser)
+ )
+
+ assertThat(repository.isEnabled(testUser).value).isEqualTo(!wasEnabled)
+ }
+
+ @Test
+ fun handleClickWhenDisabled() = runTest {
+ val wasEnabled = false
+ repository.setIsEnabled(wasEnabled, testUser)
+
+ underTest.handleInput(
+ QSTileInputTestKtx.click(OneHandedModeTileModel(wasEnabled), testUser)
+ )
+
+ assertThat(repository.isEnabled(testUser).value).isEqualTo(!wasEnabled)
+ }
+
+ @Test
+ fun handleLongClickWhenDisabled() = runTest {
+ val enabled = false
+
+ underTest.handleInput(
+ QSTileInputTestKtx.longClick(OneHandedModeTileModel(enabled), testUser)
+ )
+
+ QSTileIntentUserInputHandlerSubject.assertThat(inputHandler).handledOneIntentInput {
+ assertThat(it.intent.action).isEqualTo(Settings.ACTION_ONE_HANDED_SETTINGS)
+ }
+ }
+
+ @Test
+ fun handleLongClickWhenEnabled() = runTest {
+ val enabled = true
+
+ underTest.handleInput(
+ QSTileInputTestKtx.longClick(OneHandedModeTileModel(enabled), testUser)
+ )
+
+ QSTileIntentUserInputHandlerSubject.assertThat(inputHandler).handledOneIntentInput {
+ assertThat(it.intent.action).isEqualTo(Settings.ACTION_ONE_HANDED_SETTINGS)
+ }
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/onehanded/ui/OneHandedModeTileMapperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/onehanded/ui/OneHandedModeTileMapperTest.kt
new file mode 100644
index 0000000..7ef020d
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/onehanded/ui/OneHandedModeTileMapperTest.kt
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.onehanded.ui
+
+import android.graphics.drawable.TestStubDrawable
+import android.widget.Switch
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.common.shared.model.Icon
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.qs.tileimpl.SubtitleArrayMapping
+import com.android.systemui.qs.tiles.impl.custom.QSTileStateSubject
+import com.android.systemui.qs.tiles.impl.onehanded.domain.model.OneHandedModeTileModel
+import com.android.systemui.qs.tiles.impl.onehanded.qsOneHandedModeTileConfig
+import com.android.systemui.qs.tiles.viewmodel.QSTileState
+import com.android.systemui.res.R
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class OneHandedModeTileMapperTest : SysuiTestCase() {
+ private val kosmos = Kosmos()
+ private val config = kosmos.qsOneHandedModeTileConfig
+ private val subtitleArrayId = SubtitleArrayMapping.getSubtitleId(config.tileSpec.spec)
+ private val subtitleArray by lazy { context.resources.getStringArray(subtitleArrayId) }
+
+ private lateinit var mapper: OneHandedModeTileMapper
+
+ @Before
+ fun setup() {
+ mapper =
+ OneHandedModeTileMapper(
+ context.orCreateTestableResources
+ .apply {
+ addOverride(
+ com.android.internal.R.drawable.ic_qs_one_handed_mode,
+ TestStubDrawable()
+ )
+ }
+ .resources,
+ context.theme
+ )
+ }
+
+ @Test
+ fun disabledModel() {
+ val inputModel = OneHandedModeTileModel(false)
+
+ val outputState = mapper.map(config, inputModel)
+
+ val expectedState =
+ createOneHandedModeTileState(
+ QSTileState.ActivationState.INACTIVE,
+ subtitleArray[1],
+ com.android.internal.R.drawable.ic_qs_one_handed_mode
+ )
+ QSTileStateSubject.assertThat(outputState).isEqualTo(expectedState)
+ }
+
+ @Test
+ fun enabledModel() {
+ val inputModel = OneHandedModeTileModel(true)
+
+ val outputState = mapper.map(config, inputModel)
+
+ val expectedState =
+ createOneHandedModeTileState(
+ QSTileState.ActivationState.ACTIVE,
+ subtitleArray[2],
+ com.android.internal.R.drawable.ic_qs_one_handed_mode
+ )
+ QSTileStateSubject.assertThat(outputState).isEqualTo(expectedState)
+ }
+
+ private fun createOneHandedModeTileState(
+ activationState: QSTileState.ActivationState,
+ secondaryLabel: String,
+ iconRes: Int,
+ ): QSTileState {
+ val label = context.getString(R.string.quick_settings_onehanded_label)
+ return QSTileState(
+ { Icon.Loaded(context.getDrawable(iconRes)!!, null) },
+ label,
+ activationState,
+ secondaryLabel,
+ setOf(QSTileState.UserAction.CLICK, QSTileState.UserAction.LONG_CLICK),
+ label,
+ null,
+ QSTileState.SideViewIcon.None,
+ QSTileState.EnabledState.ENABLED,
+ Switch::class.qualifiedName
+ )
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/screenrecord/domain/interactor/ScreenRecordTileUserActionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/screenrecord/domain/interactor/ScreenRecordTileUserActionInteractorTest.kt
index b9321d5..91f4ea8 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/screenrecord/domain/interactor/ScreenRecordTileUserActionInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/screenrecord/domain/interactor/ScreenRecordTileUserActionInteractorTest.kt
@@ -18,12 +18,11 @@
import android.app.Dialog
import android.os.UserHandle
-import android.view.View
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.DialogTransitionAnimator
-import com.android.systemui.animation.dialogTransitionAnimator
+import com.android.systemui.animation.Expandable
import com.android.systemui.flags.featureFlagsClassic
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
@@ -138,12 +137,17 @@
*/
@Test
fun handleClickFromView_whenDoingNothing_whenKeyguardNotShowing_showDialogFromView() = runTest {
- val view = mock<View>()
+ val expandable = mock<Expandable>()
+ val controller = mock<DialogTransitionAnimator.Controller>()
+ whenever(expandable.dialogTransitionController(any())).thenReturn(controller)
+
kosmos.fakeKeyguardRepository.setKeyguardShowing(false)
val recordingModel = ScreenRecordTileModel.DoingNothing
- underTest.handleInput(QSTileInputTestKtx.click(recordingModel, UserHandle.CURRENT, view))
+ underTest.handleInput(
+ QSTileInputTestKtx.click(recordingModel, UserHandle.CURRENT, expandable)
+ )
val onStartRecordingClickedCaptor = argumentCaptor<Runnable>()
verify(recordingController)
.createScreenRecordDialog(
@@ -158,6 +162,6 @@
verify(keyguardDismissUtil)
.executeWhenUnlocked(onDismissActionCaptor.capture(), eq(false), eq(true))
onDismissActionCaptor.value.onDismiss()
- verify(dialogTransitionAnimator).showFromView(eq(dialog), eq(view), any(), eq(true))
+ verify(dialogTransitionAnimator).show(eq(dialog), eq(controller), eq(true))
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/adapter/QSSceneAdapterImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/adapter/QSSceneAdapterImplTest.kt
index f2eb7f4..c660ff3 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/adapter/QSSceneAdapterImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/adapter/QSSceneAdapterImplTest.kt
@@ -273,21 +273,56 @@
}
@Test
- fun customizing_QS() =
+ fun customizing_QS_noAnimations() =
testScope.runTest {
- val customizing by collectLastValue(underTest.isCustomizing)
+ val customizerState by collectLastValue(underTest.customizerState)
underTest.inflate(context)
runCurrent()
underTest.setState(QSSceneAdapter.State.QS)
- assertThat(customizing).isFalse()
+ assertThat(customizerState).isEqualTo(CustomizerState.Hidden)
underTest.setCustomizerShowing(true)
- assertThat(customizing).isTrue()
+ assertThat(customizerState).isEqualTo(CustomizerState.Showing)
underTest.setCustomizerShowing(false)
- assertThat(customizing).isFalse()
+ assertThat(customizerState).isEqualTo(CustomizerState.Hidden)
+ }
+
+ // This matches the calls made by QSCustomizer
+ @Test
+ fun customizing_QS_animations_correctStates() =
+ testScope.runTest {
+ val customizerState by collectLastValue(underTest.customizerState)
+ val animatingInDuration = 100L
+ val animatingOutDuration = 50L
+
+ underTest.inflate(context)
+ runCurrent()
+ underTest.setState(QSSceneAdapter.State.QS)
+
+ assertThat(customizerState).isEqualTo(CustomizerState.Hidden)
+
+ // Start showing customizer with animation
+ underTest.setCustomizerAnimating(true)
+ underTest.setCustomizerShowing(true, animatingInDuration)
+ assertThat(customizerState)
+ .isEqualTo(CustomizerState.AnimatingIntoCustomizer(animatingInDuration))
+
+ // Finish animation
+ underTest.setCustomizerAnimating(false)
+ assertThat(customizerState).isEqualTo(CustomizerState.Showing)
+
+ // Start closing customizer with animation
+ underTest.setCustomizerAnimating(true)
+ underTest.setCustomizerShowing(false, animatingOutDuration)
+ assertThat(customizerState)
+ .isEqualTo(CustomizerState.AnimatingOutOfCustomizer(animatingOutDuration))
+
+ // Finish animation
+ underTest.setCustomizerAnimating(false)
+ assertThat(customizerState).isEqualTo(CustomizerState.Hidden)
}
@Test
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneViewModelTest.kt
new file mode 100644
index 0000000..034c2e9
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneViewModelTest.kt
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.ui.viewmodel
+
+import android.testing.TestableLooper
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.compose.animation.scene.Swipe
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository
+import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.deviceentry.data.repository.fakeDeviceEntryRepository
+import com.android.systemui.deviceentry.domain.interactor.deviceUnlockedInteractor
+import com.android.systemui.flags.EnableSceneContainer
+import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository
+import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.scene.domain.interactor.sceneInteractor
+import com.android.systemui.scene.shared.model.Scenes
+import com.android.systemui.shade.ui.viewmodel.quickSettingsShadeSceneViewModel
+import com.android.systemui.testKosmos
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+@TestableLooper.RunWithLooper
+@EnableSceneContainer
+class QuickSettingsShadeSceneViewModelTest : SysuiTestCase() {
+
+ private val kosmos = testKosmos()
+ private val testScope = kosmos.testScope
+ private val sceneInteractor = kosmos.sceneInteractor
+ private val deviceUnlockedInteractor = kosmos.deviceUnlockedInteractor
+
+ private val underTest = kosmos.quickSettingsShadeSceneViewModel
+
+ @Test
+ fun upTransitionSceneKey_deviceLocked_lockscreen() =
+ testScope.runTest {
+ val destinationScenes by collectLastValue(underTest.destinationScenes)
+ lockDevice()
+
+ assertThat(destinationScenes?.get(Swipe.Up)?.toScene).isEqualTo(Scenes.Lockscreen)
+ }
+
+ @Test
+ fun upTransitionSceneKey_deviceUnlocked_gone() =
+ testScope.runTest {
+ val destinationScenes by collectLastValue(underTest.destinationScenes)
+ lockDevice()
+ unlockDevice()
+
+ assertThat(destinationScenes?.get(Swipe.Up)?.toScene).isEqualTo(Scenes.Gone)
+ }
+
+ @Test
+ fun upTransitionSceneKey_authMethodSwipe_lockscreenNotDismissed_goesToLockscreen() =
+ testScope.runTest {
+ val destinationScenes by collectLastValue(underTest.destinationScenes)
+ kosmos.fakeDeviceEntryRepository.setLockscreenEnabled(true)
+ kosmos.fakeAuthenticationRepository.setAuthenticationMethod(
+ AuthenticationMethodModel.None
+ )
+ sceneInteractor.changeScene(Scenes.Lockscreen, "reason")
+
+ assertThat(destinationScenes?.get(Swipe.Up)?.toScene).isEqualTo(Scenes.Lockscreen)
+ }
+
+ @Test
+ fun upTransitionSceneKey_authMethodSwipe_lockscreenDismissed_goesToGone() =
+ testScope.runTest {
+ val destinationScenes by collectLastValue(underTest.destinationScenes)
+ kosmos.fakeDeviceEntryRepository.setLockscreenEnabled(true)
+ kosmos.fakeAuthenticationRepository.setAuthenticationMethod(
+ AuthenticationMethodModel.None
+ )
+ runCurrent()
+ sceneInteractor.changeScene(Scenes.Gone, "reason")
+
+ assertThat(destinationScenes?.get(Swipe.Up)?.toScene).isEqualTo(Scenes.Gone)
+ }
+
+ private fun TestScope.lockDevice() {
+ val deviceUnlockStatus by collectLastValue(deviceUnlockedInteractor.deviceUnlockStatus)
+
+ kosmos.fakeAuthenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
+ assertThat(deviceUnlockStatus?.isUnlocked).isFalse()
+ sceneInteractor.changeScene(Scenes.Lockscreen, "reason")
+ runCurrent()
+ }
+
+ private fun TestScope.unlockDevice() {
+ val deviceUnlockStatus by collectLastValue(deviceUnlockedInteractor.deviceUnlockStatus)
+
+ kosmos.fakeDeviceEntryFingerprintAuthRepository.setAuthenticationStatus(
+ SuccessFingerprintAuthenticationStatus(0, true)
+ )
+ assertThat(deviceUnlockStatus?.isUnlocked).isTrue()
+ sceneInteractor.changeScene(Scenes.Gone, "reason")
+ runCurrent()
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
index 6643bcb..4cb8bf8 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
@@ -496,7 +496,7 @@
*/
private fun getCurrentSceneInUi(): SceneKey {
return when (val state = transitionState.value) {
- is ObservableTransitionState.Idle -> state.scene
+ is ObservableTransitionState.Idle -> state.currentScene
is ObservableTransitionState.Transition -> state.fromScene
}
}
@@ -558,6 +558,7 @@
ObservableTransitionState.Transition(
fromScene = getCurrentSceneInUi(),
toScene = to,
+ currentScene = flowOf(to),
progress = progressFlow,
isInitiatedByUserInput = false,
isUserInputOngoing = flowOf(false),
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryTest.kt
index a45ac9f..df30c4b 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryTest.kt
@@ -70,6 +70,9 @@
underTest.changeScene(Scenes.Shade)
assertThat(currentScene).isEqualTo(Scenes.Shade)
+
+ underTest.snapToScene(Scenes.QuickSettings)
+ assertThat(currentScene).isEqualTo(Scenes.QuickSettings)
}
@Test(expected = IllegalStateException::class)
@@ -79,6 +82,13 @@
underTest.changeScene(Scenes.Shade)
}
+ @Test(expected = IllegalStateException::class)
+ fun snapToScene_noSuchSceneInContainer_throws() {
+ kosmos.sceneKeys = listOf(Scenes.QuickSettings, Scenes.Lockscreen)
+ val underTest = kosmos.sceneContainerRepository
+ underTest.snapToScene(Scenes.Shade)
+ }
+
@Test
fun isVisible() =
testScope.runTest {
@@ -122,6 +132,7 @@
ObservableTransitionState.Transition(
fromScene = Scenes.Lockscreen,
toScene = Scenes.Shade,
+ currentScene = flowOf(Scenes.Shade),
progress = progress,
isInitiatedByUserInput = false,
isUserInputOngoing = flowOf(false),
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneContainerOcclusionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneContainerOcclusionInteractorTest.kt
index c3366ad..edaa3d3 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneContainerOcclusionInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneContainerOcclusionInteractorTest.kt
@@ -152,6 +152,7 @@
ObservableTransitionState.Transition(
fromScene = sceneDataSource.currentScene.value,
toScene = Scenes.Shade,
+ currentScene = flowOf(sceneDataSource.currentScene.value),
progress = progress,
isInitiatedByUserInput = true,
isUserInputOngoing = flowOf(true),
@@ -178,6 +179,7 @@
ObservableTransitionState.Transition(
fromScene = Scenes.Shade,
toScene = Scenes.Lockscreen,
+ currentScene = flowOf(Scenes.Shade),
progress = progress,
isInitiatedByUserInput = true,
isUserInputOngoing = flowOf(true),
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt
index f58e01f..2fa94ef 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt
@@ -126,6 +126,71 @@
}
@Test
+ fun snapToScene_toUnknownScene_doesNothing() =
+ testScope.runTest {
+ val sceneKeys =
+ listOf(
+ Scenes.QuickSettings,
+ Scenes.Shade,
+ Scenes.Lockscreen,
+ Scenes.Gone,
+ Scenes.Communal,
+ )
+ val navigationDistances =
+ mapOf(
+ Scenes.Gone to 0,
+ Scenes.Lockscreen to 0,
+ Scenes.Communal to 1,
+ Scenes.Shade to 2,
+ Scenes.QuickSettings to 3,
+ )
+ kosmos.sceneContainerConfig =
+ SceneContainerConfig(sceneKeys, Scenes.Lockscreen, navigationDistances)
+ underTest = kosmos.sceneInteractor
+ val currentScene by collectLastValue(underTest.currentScene)
+ val previousScene = currentScene
+ assertThat(previousScene).isNotEqualTo(Scenes.Bouncer)
+ underTest.snapToScene(Scenes.Bouncer, "reason")
+ assertThat(currentScene).isEqualTo(previousScene)
+ }
+
+ @Test
+ fun snapToScene() =
+ testScope.runTest {
+ underTest = kosmos.sceneInteractor
+
+ val currentScene by collectLastValue(underTest.currentScene)
+ assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
+
+ underTest.snapToScene(Scenes.Shade, "reason")
+ assertThat(currentScene).isEqualTo(Scenes.Shade)
+ }
+
+ @Test
+ fun snapToScene_toGoneWhenUnl_doesNotThrow() =
+ testScope.runTest {
+ underTest = kosmos.sceneInteractor
+
+ val currentScene by collectLastValue(underTest.currentScene)
+ assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
+
+ kosmos.fakeDeviceEntryFingerprintAuthRepository.setAuthenticationStatus(
+ SuccessFingerprintAuthenticationStatus(0, true)
+ )
+ runCurrent()
+
+ underTest.snapToScene(Scenes.Gone, "reason")
+ assertThat(currentScene).isEqualTo(Scenes.Gone)
+ }
+
+ @Test(expected = IllegalStateException::class)
+ fun snapToScene_toGoneWhenStillLocked_throws() =
+ testScope.runTest {
+ underTest = kosmos.sceneInteractor
+ underTest.snapToScene(Scenes.Gone, "reason")
+ }
+
+ @Test
fun sceneChanged_inDataSource() =
testScope.runTest {
underTest = kosmos.sceneInteractor
@@ -155,6 +220,7 @@
ObservableTransitionState.Transition(
fromScene = Scenes.Lockscreen,
toScene = Scenes.Shade,
+ currentScene = flowOf(Scenes.Shade),
progress = progress,
isInitiatedByUserInput = false,
isUserInputOngoing = flowOf(false),
@@ -195,6 +261,7 @@
ObservableTransitionState.Transition(
fromScene = underTest.currentScene.value,
toScene = Scenes.Shade,
+ currentScene = flowOf(Scenes.Shade),
progress = progress,
isInitiatedByUserInput = false,
isUserInputOngoing = flowOf(false),
@@ -235,6 +302,7 @@
ObservableTransitionState.Transition(
fromScene = Scenes.Shade,
toScene = Scenes.Lockscreen,
+ currentScene = flowOf(Scenes.Shade),
progress = flowOf(0.5f),
isInitiatedByUserInput = true,
isUserInputOngoing = flowOf(true),
@@ -256,6 +324,7 @@
ObservableTransitionState.Transition(
fromScene = Scenes.Shade,
toScene = Scenes.Lockscreen,
+ currentScene = flowOf(Scenes.Shade),
progress = flowOf(0.5f),
isInitiatedByUserInput = true,
isUserInputOngoing = flowOf(true),
@@ -271,6 +340,7 @@
ObservableTransitionState.Transition(
fromScene = Scenes.Shade,
toScene = Scenes.Lockscreen,
+ currentScene = flowOf(Scenes.Lockscreen),
progress = flowOf(0.6f),
isInitiatedByUserInput = true,
isUserInputOngoing = flowOf(false),
@@ -288,6 +358,7 @@
ObservableTransitionState.Transition(
fromScene = Scenes.Shade,
toScene = Scenes.Lockscreen,
+ currentScene = flowOf(Scenes.Shade),
progress = flowOf(0.5f),
isInitiatedByUserInput = true,
isUserInputOngoing = flowOf(true),
@@ -299,7 +370,7 @@
assertThat(isTransitionUserInputOngoing).isTrue()
- transitionState.value = ObservableTransitionState.Idle(scene = Scenes.Lockscreen)
+ transitionState.value = ObservableTransitionState.Idle(currentScene = Scenes.Lockscreen)
assertThat(isTransitionUserInputOngoing).isFalse()
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
index 5779e37..93465c8 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
@@ -135,6 +135,7 @@
ObservableTransitionState.Transition(
fromScene = Scenes.Gone,
toScene = Scenes.Shade,
+ currentScene = flowOf(Scenes.Shade),
progress = flowOf(0.5f),
isInitiatedByUserInput = false,
isUserInputOngoing = flowOf(false),
@@ -150,6 +151,7 @@
ObservableTransitionState.Transition(
fromScene = Scenes.Shade,
toScene = Scenes.Gone,
+ currentScene = flowOf(Scenes.Gone),
progress = flowOf(0.5f),
isInitiatedByUserInput = false,
isUserInputOngoing = flowOf(false),
@@ -521,6 +523,7 @@
ObservableTransitionState.Transition(
fromScene = Scenes.Gone,
toScene = Scenes.Lockscreen,
+ currentScene = flowOf(Scenes.Lockscreen),
progress = flowOf(0.1f),
isInitiatedByUserInput = false,
isUserInputOngoing = flowOf(false),
@@ -871,6 +874,7 @@
ObservableTransitionState.Transition(
fromScene = Scenes.Gone,
toScene = Scenes.Shade,
+ currentScene = flowOf(Scenes.Shade),
progress = flowOf(0.5f),
isInitiatedByUserInput = false,
isUserInputOngoing = flowOf(false),
@@ -889,6 +893,7 @@
ObservableTransitionState.Transition(
fromScene = Scenes.Shade,
toScene = Scenes.Gone,
+ currentScene = flowOf(Scenes.Gone),
progress = flowOf(0.5f),
isInitiatedByUserInput = false,
isUserInputOngoing = flowOf(false),
@@ -1203,6 +1208,7 @@
ObservableTransitionState.Transition(
fromScene = Scenes.Bouncer,
toScene = Scenes.Lockscreen,
+ currentScene = flowOf(Scenes.Bouncer),
progress = flowOf(-0.4f),
isInitiatedByUserInput = true,
isUserInputOngoing = flowOf(true),
@@ -1225,6 +1231,7 @@
ObservableTransitionState.Transition(
fromScene = Scenes.Lockscreen,
toScene = Scenes.Bouncer,
+ currentScene = flowOf(Scenes.Bouncer),
progress = flowOf(0.9f),
isInitiatedByUserInput = true,
isUserInputOngoing = flowOf(false),
@@ -1274,6 +1281,7 @@
ObservableTransitionState.Transition(
fromScene = fromScene,
toScene = toScene,
+ currentScene = flowOf(fromScene),
progress = flowOf(0.5f),
isInitiatedByUserInput = true,
isUserInputOngoing = flowOf(true),
@@ -1283,7 +1291,7 @@
transitionStateFlow.value =
ObservableTransitionState.Idle(
- scene = toScene,
+ currentScene = toScene,
)
runCurrent()
verifyAfterTransition?.invoke()
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
index 66f7416..d6e3879 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
@@ -20,7 +20,7 @@
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
-import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_SENSITIVE_FOR_TRACING;
+import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_SENSITIVE_FOR_PRIVACY;
import static com.google.common.truth.Truth.assertThat;
@@ -79,12 +79,12 @@
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
-import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
-import platform.test.runner.parameterized.Parameters;
-
import java.util.List;
import java.util.concurrent.Executor;
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
+import platform.test.runner.parameterized.Parameters;
+
@RunWith(ParameterizedAndroidJunit4.class)
@RunWithLooper(setAsMainLooper = true)
@SmallTest
@@ -341,7 +341,7 @@
verify(mWindowManager).updateViewLayout(any(), mLayoutParameters.capture());
assertThat((mLayoutParameters.getValue().flags & FLAG_SECURE) != 0).isTrue();
assertThat(
- (mLayoutParameters.getValue().inputFeatures & INPUT_FEATURE_SENSITIVE_FOR_TRACING)
+ (mLayoutParameters.getValue().inputFeatures & INPUT_FEATURE_SENSITIVE_FOR_PRIVACY)
!= 0)
.isTrue();
}
@@ -353,7 +353,7 @@
verify(mWindowManager).updateViewLayout(any(), mLayoutParameters.capture());
assertThat((mLayoutParameters.getValue().flags & FLAG_SECURE) == 0).isTrue();
assertThat(
- (mLayoutParameters.getValue().inputFeatures & INPUT_FEATURE_SENSITIVE_FOR_TRACING)
+ (mLayoutParameters.getValue().inputFeatures & INPUT_FEATURE_SENSITIVE_FOR_PRIVACY)
== 0)
.isTrue();
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/PanelExpansionInteractorImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/PanelExpansionInteractorImplTest.kt
index 6485c47..e11a8f1 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/PanelExpansionInteractorImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/PanelExpansionInteractorImplTest.kt
@@ -166,6 +166,7 @@
ObservableTransitionState.Transition(
fromScene = checkNotNull(currentScene),
toScene = toScene,
+ currentScene = flowOf(checkNotNull(currentScene)),
progress = progressFlow,
isInitiatedByUserInput = true,
isUserInputOngoing = flowOf(true),
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractorSceneContainerImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractorSceneContainerImplTest.kt
index bb40591..aef9163 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractorSceneContainerImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractorSceneContainerImplTest.kt
@@ -55,6 +55,7 @@
ObservableTransitionState.Transition(
fromScene = Scenes.QuickSettings,
toScene = Scenes.Shade,
+ currentScene = flowOf(Scenes.Shade),
progress = MutableStateFlow(.1f),
isInitiatedByUserInput = false,
isUserInputOngoing = flowOf(false),
@@ -78,6 +79,7 @@
ObservableTransitionState.Transition(
fromScene = Scenes.QuickSettings,
toScene = Scenes.Gone,
+ currentScene = flowOf(Scenes.Gone),
progress = MutableStateFlow(.1f),
isInitiatedByUserInput = false,
isUserInputOngoing = flowOf(false),
@@ -101,6 +103,7 @@
ObservableTransitionState.Transition(
fromScene = Scenes.QuickSettings,
toScene = Scenes.Gone,
+ currentScene = flowOf(Scenes.QuickSettings),
progress = MutableStateFlow(.1f),
isInitiatedByUserInput = false,
isUserInputOngoing = flowOf(true),
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImplTest.kt
index e1908b9..b1bffdb 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImplTest.kt
@@ -69,6 +69,7 @@
ObservableTransitionState.Transition(
fromScene = Scenes.QuickSettings,
toScene = Scenes.Shade,
+ currentScene = flowOf(Scenes.Shade),
progress = MutableStateFlow(.3f),
isInitiatedByUserInput = false,
isUserInputOngoing = flowOf(false),
@@ -98,6 +99,7 @@
ObservableTransitionState.Transition(
fromScene = Scenes.QuickSettings,
toScene = Scenes.Shade,
+ currentScene = flowOf(Scenes.Shade),
progress = progress,
isInitiatedByUserInput = false,
isUserInputOngoing = flowOf(false),
@@ -122,6 +124,7 @@
ObservableTransitionState.Transition(
fromScene = Scenes.QuickSettings,
toScene = Scenes.Shade,
+ currentScene = flowOf(Scenes.Shade),
progress = MutableStateFlow(.3f),
isInitiatedByUserInput = false,
isUserInputOngoing = flowOf(false),
@@ -220,6 +223,7 @@
ObservableTransitionState.Transition(
fromScene = Scenes.Lockscreen,
toScene = key,
+ currentScene = flowOf(key),
progress = progress,
isInitiatedByUserInput = false,
isUserInputOngoing = flowOf(false),
@@ -258,6 +262,7 @@
ObservableTransitionState.Transition(
fromScene = key,
toScene = Scenes.Lockscreen,
+ currentScene = flowOf(Scenes.Lockscreen),
progress = progress,
isInitiatedByUserInput = false,
isUserInputOngoing = flowOf(false),
@@ -292,6 +297,7 @@
ObservableTransitionState.Transition(
fromScene = Scenes.Gone,
toScene = Scenes.QuickSettings,
+ currentScene = flowOf(Scenes.QuickSettings),
progress = MutableStateFlow(.1f),
isInitiatedByUserInput = false,
isUserInputOngoing = flowOf(false),
@@ -315,6 +321,7 @@
ObservableTransitionState.Transition(
fromScene = Scenes.Shade,
toScene = Scenes.QuickSettings,
+ currentScene = flowOf(Scenes.QuickSettings),
progress = MutableStateFlow(.1f),
isInitiatedByUserInput = false,
isUserInputOngoing = flowOf(false),
@@ -341,6 +348,7 @@
ObservableTransitionState.Transition(
fromScene = Scenes.Lockscreen,
toScene = Scenes.Shade,
+ currentScene = flowOf(Scenes.Shade),
progress = progress,
isInitiatedByUserInput = false,
isUserInputOngoing = flowOf(false),
@@ -396,6 +404,7 @@
ObservableTransitionState.Transition(
fromScene = Scenes.Lockscreen,
toScene = key,
+ currentScene = flowOf(key),
progress = progress,
isInitiatedByUserInput = false,
isUserInputOngoing = flowOf(false),
@@ -434,6 +443,7 @@
ObservableTransitionState.Transition(
fromScene = Scenes.Lockscreen,
toScene = key,
+ currentScene = flowOf(key),
progress = progress,
isInitiatedByUserInput = true,
isUserInputOngoing = flowOf(false),
@@ -472,6 +482,7 @@
ObservableTransitionState.Transition(
fromScene = key,
toScene = Scenes.Lockscreen,
+ currentScene = flowOf(Scenes.Lockscreen),
progress = progress,
isInitiatedByUserInput = false,
isUserInputOngoing = flowOf(false),
@@ -510,6 +521,7 @@
ObservableTransitionState.Transition(
fromScene = key,
toScene = Scenes.Lockscreen,
+ currentScene = flowOf(Scenes.Lockscreen),
progress = progress,
isInitiatedByUserInput = true,
isUserInputOngoing = flowOf(false),
@@ -547,6 +559,7 @@
ObservableTransitionState.Transition(
fromScene = Scenes.Lockscreen,
toScene = Scenes.QuickSettings,
+ currentScene = flowOf(Scenes.QuickSettings),
progress = MutableStateFlow(0f),
isInitiatedByUserInput = true,
isUserInputOngoing = flowOf(false),
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/startable/ShadeStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/startable/ShadeStartableTest.kt
index 07c4b00..44c9695 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/startable/ShadeStartableTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/startable/ShadeStartableTest.kt
@@ -16,6 +16,8 @@
package com.android.systemui.shade.domain.startable
+import android.platform.test.annotations.DisableFlags
+import android.platform.test.annotations.EnableFlags
import android.platform.test.flag.junit.FlagsParameterization
import androidx.test.filters.SmallTest
import com.android.compose.animation.scene.ObservableTransitionState
@@ -37,6 +39,7 @@
import com.android.systemui.shade.ShadeExpansionChangeEvent
import com.android.systemui.shade.ShadeExpansionListener
import com.android.systemui.shade.domain.interactor.shadeInteractor
+import com.android.systemui.shade.shared.flag.DualShade
import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.any
@@ -49,7 +52,6 @@
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
-import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import platform.test.runner.parameterized.ParameterizedAndroidJunit4
@@ -67,7 +69,7 @@
private val fakeConfigurationRepository by lazy { kosmos.fakeConfigurationRepository }
private val fakeSceneDataSource by lazy { kosmos.fakeSceneDataSource }
- private lateinit var underTest: ShadeStartable
+ private val underTest: ShadeStartable = kosmos.shadeStartable
companion object {
@JvmStatic
@@ -81,13 +83,9 @@
mSetFlagsRule.setFlagsParameterization(flags!!)
}
- @Before
- fun setup() {
- underTest = kosmos.shadeStartable
- }
-
@Test
- fun hydrateShadeMode() =
+ @DisableFlags(DualShade.FLAG_NAME)
+ fun hydrateShadeMode_dualShadeDisabled() =
testScope.runTest {
overrideResource(R.bool.config_use_split_notification_shade, false)
val shadeMode by collectLastValue(shadeInteractor.shadeMode)
@@ -105,6 +103,25 @@
}
@Test
+ @EnableFlags(DualShade.FLAG_NAME)
+ fun hydrateShadeMode_dualShadeEnabled() =
+ testScope.runTest {
+ overrideResource(R.bool.config_use_split_notification_shade, false)
+ val shadeMode by collectLastValue(shadeInteractor.shadeMode)
+
+ underTest.start()
+ assertThat(shadeMode).isEqualTo(ShadeMode.Dual)
+
+ overrideResource(R.bool.config_use_split_notification_shade, true)
+ fakeConfigurationRepository.onAnyConfigurationChange()
+ assertThat(shadeMode).isEqualTo(ShadeMode.Dual)
+
+ overrideResource(R.bool.config_use_split_notification_shade, false)
+ fakeConfigurationRepository.onAnyConfigurationChange()
+ assertThat(shadeMode).isEqualTo(ShadeMode.Dual)
+ }
+
+ @Test
@EnableSceneContainer
fun hydrateShadeExpansionStateManager() =
testScope.runTest {
@@ -161,6 +178,7 @@
ObservableTransitionState.Transition(
fromScene = checkNotNull(currentScene),
toScene = toScene,
+ currentScene = flowOf(checkNotNull(currentScene)),
progress = progressFlow,
isInitiatedByUserInput = true,
isUserInputOngoing = flowOf(true),
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/OverlayShadeViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/OverlayShadeViewModelTest.kt
new file mode 100644
index 0000000..0ffabd8
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/OverlayShadeViewModelTest.kt
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shade.ui.viewmodel
+
+import android.testing.TestableLooper
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository
+import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.deviceentry.data.repository.fakeDeviceEntryRepository
+import com.android.systemui.deviceentry.domain.interactor.deviceUnlockedInteractor
+import com.android.systemui.flags.EnableSceneContainer
+import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository
+import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.scene.domain.interactor.sceneInteractor
+import com.android.systemui.scene.shared.model.Scenes
+import com.android.systemui.testKosmos
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+@TestableLooper.RunWithLooper
+@EnableSceneContainer
+class OverlayShadeViewModelTest : SysuiTestCase() {
+
+ private val kosmos = testKosmos()
+ private val testScope = kosmos.testScope
+ private val sceneInteractor = kosmos.sceneInteractor
+ private val deviceUnlockedInteractor by lazy { kosmos.deviceUnlockedInteractor }
+
+ private val underTest = kosmos.overlayShadeViewModel
+
+ @Test
+ fun backgroundScene_deviceLocked_lockscreen() =
+ testScope.runTest {
+ val backgroundScene by collectLastValue(underTest.backgroundScene)
+
+ lockDevice()
+
+ assertThat(backgroundScene).isEqualTo(Scenes.Lockscreen)
+ }
+
+ @Test
+ fun backgroundScene_deviceUnlocked_gone() =
+ testScope.runTest {
+ val backgroundScene by collectLastValue(underTest.backgroundScene)
+
+ lockDevice()
+ unlockDevice()
+
+ assertThat(backgroundScene).isEqualTo(Scenes.Gone)
+ }
+
+ @Test
+ fun backgroundScene_authMethodSwipe_lockscreenNotDismissed_goesToLockscreen() =
+ testScope.runTest {
+ val backgroundScene by collectLastValue(underTest.backgroundScene)
+ val deviceUnlockStatus by collectLastValue(deviceUnlockedInteractor.deviceUnlockStatus)
+
+ kosmos.fakeDeviceEntryRepository.setLockscreenEnabled(true)
+ kosmos.fakeAuthenticationRepository.setAuthenticationMethod(
+ AuthenticationMethodModel.None
+ )
+ assertThat(deviceUnlockStatus?.isUnlocked).isTrue()
+ sceneInteractor.changeScene(Scenes.Lockscreen, "reason")
+ runCurrent()
+
+ assertThat(backgroundScene).isEqualTo(Scenes.Lockscreen)
+ }
+
+ @Test
+ fun backgroundScene_authMethodSwipe_lockscreenDismissed_goesToGone() =
+ testScope.runTest {
+ val backgroundScene by collectLastValue(underTest.backgroundScene)
+ val deviceUnlockStatus by collectLastValue(deviceUnlockedInteractor.deviceUnlockStatus)
+
+ kosmos.fakeDeviceEntryRepository.setLockscreenEnabled(true)
+ kosmos.fakeAuthenticationRepository.setAuthenticationMethod(
+ AuthenticationMethodModel.None
+ )
+ assertThat(deviceUnlockStatus?.isUnlocked).isTrue()
+ sceneInteractor.changeScene(Scenes.Gone, "reason")
+ runCurrent()
+
+ assertThat(backgroundScene).isEqualTo(Scenes.Gone)
+ }
+
+ @Test
+ fun onScrimClicked_onLockscreen_goesToLockscreen() =
+ testScope.runTest {
+ val currentScene by collectLastValue(sceneInteractor.currentScene)
+ lockDevice()
+ sceneInteractor.changeScene(Scenes.Bouncer, "reason")
+ runCurrent()
+ assertThat(currentScene).isNotEqualTo(Scenes.Lockscreen)
+
+ underTest.onScrimClicked()
+
+ assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
+ }
+
+ @Test
+ fun onScrimClicked_deviceWasEntered_goesToGone() =
+ testScope.runTest {
+ val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val backgroundScene by collectLastValue(underTest.backgroundScene)
+
+ lockDevice()
+ unlockDevice()
+ sceneInteractor.changeScene(Scenes.QuickSettings, "reason")
+ runCurrent()
+ assertThat(backgroundScene).isEqualTo(Scenes.Gone)
+ assertThat(currentScene).isNotEqualTo(Scenes.Gone)
+
+ underTest.onScrimClicked()
+
+ assertThat(currentScene).isEqualTo(Scenes.Gone)
+ }
+
+ private fun TestScope.lockDevice() {
+ val deviceUnlockStatus by collectLastValue(deviceUnlockedInteractor.deviceUnlockStatus)
+
+ kosmos.fakeAuthenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
+ assertThat(deviceUnlockStatus?.isUnlocked).isFalse()
+ sceneInteractor.changeScene(Scenes.Lockscreen, "reason")
+ runCurrent()
+ }
+
+ private fun TestScope.unlockDevice() {
+ val deviceUnlockStatus by collectLastValue(deviceUnlockedInteractor.deviceUnlockStatus)
+
+ kosmos.fakeDeviceEntryFingerprintAuthRepository.setAuthenticationStatus(
+ SuccessFingerprintAuthenticationStatus(0, true)
+ )
+ assertThat(deviceUnlockStatus?.isUnlocked).isTrue()
+ sceneInteractor.changeScene(Scenes.Gone, "reason")
+ runCurrent()
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationScrimNestedScrollConnectionTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationScrimNestedScrollConnectionTest.kt
new file mode 100644
index 0000000..35e4047
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationScrimNestedScrollConnectionTest.kt
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification
+
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.input.nestedscroll.NestedScrollSource
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.notifications.ui.composable.NotificationScrimNestedScrollConnection
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class NotificationScrimNestedScrollConnectionTest : SysuiTestCase() {
+ private var isStarted = false
+ private var scrimOffset = 0f
+ private var contentHeight = 0f
+ private var isCurrentGestureOverscroll = false
+
+ private val scrollConnection =
+ NotificationScrimNestedScrollConnection(
+ scrimOffset = { scrimOffset },
+ snapScrimOffset = { _ -> },
+ animateScrimOffset = { _ -> },
+ minScrimOffset = { MIN_SCRIM_OFFSET },
+ maxScrimOffset = MAX_SCRIM_OFFSET,
+ contentHeight = { contentHeight },
+ minVisibleScrimHeight = { MIN_VISIBLE_SCRIM_HEIGHT },
+ isCurrentGestureOverscroll = { isCurrentGestureOverscroll },
+ onStart = { isStarted = true },
+ onStop = { isStarted = false },
+ )
+
+ @Test
+ fun onScrollUp_canStartPreScroll_contentNotExpanded_ignoreScroll() = runTest {
+ contentHeight = COLLAPSED_CONTENT_HEIGHT
+
+ val offsetConsumed =
+ scrollConnection.onPreScroll(
+ available = Offset(x = 0f, y = -1f),
+ source = NestedScrollSource.Drag,
+ )
+
+ assertThat(offsetConsumed).isEqualTo(Offset.Zero)
+ assertThat(isStarted).isEqualTo(false)
+ }
+
+ @Test
+ fun onScrollUp_canStartPreScroll_contentExpandedAtMinOffset_ignoreScroll() = runTest {
+ contentHeight = EXPANDED_CONTENT_HEIGHT
+ scrimOffset = MIN_SCRIM_OFFSET
+
+ val offsetConsumed =
+ scrollConnection.onPreScroll(
+ available = Offset(x = 0f, y = -1f),
+ source = NestedScrollSource.Drag,
+ )
+
+ assertThat(offsetConsumed).isEqualTo(Offset.Zero)
+ assertThat(isStarted).isEqualTo(false)
+ }
+
+ @Test
+ fun onScrollUp_canStartPreScroll_contentExpanded_consumeScroll() = runTest {
+ contentHeight = EXPANDED_CONTENT_HEIGHT
+
+ val availableOffset = Offset(x = 0f, y = -1f)
+ val offsetConsumed =
+ scrollConnection.onPreScroll(
+ available = availableOffset,
+ source = NestedScrollSource.Drag,
+ )
+
+ assertThat(offsetConsumed).isEqualTo(availableOffset)
+ assertThat(isStarted).isEqualTo(true)
+ }
+
+ @Test
+ fun onScrollUp_canStartPreScroll_contentExpanded_consumeScrollWithRemainder() = runTest {
+ contentHeight = EXPANDED_CONTENT_HEIGHT
+ scrimOffset = MIN_SCRIM_OFFSET + 1
+
+ val availableOffset = Offset(x = 0f, y = -2f)
+ val consumableOffset = Offset(x = 0f, y = -1f)
+ val offsetConsumed =
+ scrollConnection.onPreScroll(
+ available = availableOffset,
+ source = NestedScrollSource.Drag,
+ )
+
+ assertThat(offsetConsumed).isEqualTo(consumableOffset)
+ assertThat(isStarted).isEqualTo(true)
+ }
+
+ @Test
+ fun onScrollUp_canStartPostScroll_ignoreScroll() = runTest {
+ val offsetConsumed =
+ scrollConnection.onPostScroll(
+ consumed = Offset.Zero,
+ available = Offset(x = 0f, y = -1f),
+ source = NestedScrollSource.Drag,
+ )
+
+ assertThat(offsetConsumed).isEqualTo(Offset.Zero)
+ assertThat(isStarted).isEqualTo(false)
+ }
+
+ @Test
+ fun onScrollDown_canStartPreScroll_ignoreScroll() = runTest {
+ val offsetConsumed =
+ scrollConnection.onPreScroll(
+ available = Offset(x = 0f, y = 1f),
+ source = NestedScrollSource.Drag,
+ )
+
+ assertThat(offsetConsumed).isEqualTo(Offset.Zero)
+ assertThat(isStarted).isEqualTo(false)
+ }
+
+ @Test
+ fun onScrollDown_canStartPostScroll_consumeScroll() = runTest {
+ scrimOffset = MIN_SCRIM_OFFSET
+
+ val availableOffset = Offset(x = 0f, y = 1f)
+ val offsetConsumed =
+ scrollConnection.onPostScroll(
+ consumed = Offset.Zero,
+ available = availableOffset,
+ source = NestedScrollSource.Drag
+ )
+
+ assertThat(offsetConsumed).isEqualTo(availableOffset)
+ assertThat(isStarted).isEqualTo(true)
+ }
+
+ @Test
+ fun onScrollDown_canStartPostScroll_consumeScrollWithRemainder() = runTest {
+ scrimOffset = MAX_SCRIM_OFFSET - 1
+
+ val availableOffset = Offset(x = 0f, y = 2f)
+ val consumableOffset = Offset(x = 0f, y = 1f)
+ val offsetConsumed =
+ scrollConnection.onPostScroll(
+ consumed = Offset.Zero,
+ available = availableOffset,
+ source = NestedScrollSource.Drag
+ )
+
+ assertThat(offsetConsumed).isEqualTo(consumableOffset)
+ assertThat(isStarted).isEqualTo(true)
+ }
+
+ @Test
+ fun canStartPostScroll_atMaxOffset_ignoreScroll() = runTest {
+ scrimOffset = MAX_SCRIM_OFFSET
+
+ val offsetConsumed =
+ scrollConnection.onPostScroll(
+ consumed = Offset.Zero,
+ available = Offset(x = 0f, y = 1f),
+ source = NestedScrollSource.Drag
+ )
+
+ assertThat(offsetConsumed).isEqualTo(Offset.Zero)
+ assertThat(isStarted).isEqualTo(false)
+ }
+
+ @Test
+ fun canStartPostScroll_externalOverscrollGesture_startButIgnoreScroll() = runTest {
+ scrimOffset = MAX_SCRIM_OFFSET
+ isCurrentGestureOverscroll = true
+
+ val offsetConsumed =
+ scrollConnection.onPostScroll(
+ consumed = Offset.Zero,
+ available = Offset(x = 0f, y = 1f),
+ source = NestedScrollSource.Drag
+ )
+
+ assertThat(offsetConsumed).isEqualTo(Offset.Zero)
+ assertThat(isStarted).isEqualTo(true)
+ }
+
+ @Test
+ fun canContinueScroll_inBetweenMinMaxOffset_true() = runTest {
+ scrimOffset = (MIN_SCRIM_OFFSET + MAX_SCRIM_OFFSET) / 2f
+ contentHeight = EXPANDED_CONTENT_HEIGHT
+ scrollConnection.onPreScroll(
+ available = Offset(x = 0f, y = -1f),
+ source = NestedScrollSource.Drag
+ )
+
+ assertThat(isStarted).isEqualTo(true)
+
+ scrollConnection.onPreScroll(
+ available = Offset(x = 0f, y = 1f),
+ source = NestedScrollSource.Drag
+ )
+
+ assertThat(isStarted).isEqualTo(true)
+ }
+
+ @Test
+ fun canContinueScroll_atMaxOffset_false() = runTest {
+ scrimOffset = MAX_SCRIM_OFFSET
+ contentHeight = EXPANDED_CONTENT_HEIGHT
+ scrollConnection.onPreScroll(
+ available = Offset(x = 0f, y = -1f),
+ source = NestedScrollSource.Drag
+ )
+
+ assertThat(isStarted).isEqualTo(true)
+
+ scrollConnection.onPreScroll(
+ available = Offset(x = 0f, y = 1f),
+ source = NestedScrollSource.Drag
+ )
+
+ assertThat(isStarted).isEqualTo(false)
+ }
+
+ companion object {
+ const val MIN_SCRIM_OFFSET = -100f
+ const val MAX_SCRIM_OFFSET = 0f
+
+ const val EXPANDED_CONTENT_HEIGHT = 200f
+ const val COLLAPSED_CONTENT_HEIGHT = 40f
+
+ const val MIN_VISIBLE_SCRIM_HEIGHT = 50f
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationStackAppearanceIntegrationTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationStackAppearanceIntegrationTest.kt
index 01e1aa59..c4506f2 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationStackAppearanceIntegrationTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationStackAppearanceIntegrationTest.kt
@@ -58,7 +58,7 @@
}
private val testScope = kosmos.testScope
private val placeholderViewModel by lazy { kosmos.notificationsPlaceholderViewModel }
- private val appearanceViewModel by lazy { kosmos.notificationScrollViewModel }
+ private val scrollViewModel by lazy { kosmos.notificationScrollViewModel }
private val sceneInteractor by lazy { kosmos.sceneInteractor }
private val fakeSceneDataSource by lazy { kosmos.fakeSceneDataSource }
@@ -67,7 +67,7 @@
testScope.runTest {
val radius = MutableStateFlow(32)
val leftOffset = MutableStateFlow(0)
- val shape by collectLastValue(appearanceViewModel.shadeScrimShape(radius, leftOffset))
+ val shape by collectLastValue(scrollViewModel.shadeScrimShape(radius, leftOffset))
placeholderViewModel.onScrimBoundsChanged(
ShadeScrimBounds(left = 0f, top = 200f, right = 100f, bottom = 550f)
@@ -99,16 +99,29 @@
}
@Test
+ fun brightnessMirrorAlpha_updatesViewModel() =
+ testScope.runTest {
+ val maxAlpha by collectLastValue(scrollViewModel.maxAlpha)
+ assertThat(maxAlpha).isEqualTo(1f)
+ placeholderViewModel.setAlphaForBrightnessMirror(0.33f)
+ assertThat(maxAlpha).isEqualTo(0.33f)
+ placeholderViewModel.setAlphaForBrightnessMirror(0f)
+ assertThat(maxAlpha).isEqualTo(0f)
+ placeholderViewModel.setAlphaForBrightnessMirror(1f)
+ assertThat(maxAlpha).isEqualTo(1f)
+ }
+
+ @Test
fun shadeExpansion_goneToShade() =
testScope.runTest {
val transitionState =
MutableStateFlow<ObservableTransitionState>(
- ObservableTransitionState.Idle(scene = Scenes.Gone)
+ ObservableTransitionState.Idle(currentScene = Scenes.Gone)
)
sceneInteractor.setTransitionState(transitionState)
- val expandFraction by collectLastValue(appearanceViewModel.expandFraction)
+ val expandFraction by collectLastValue(scrollViewModel.expandFraction)
assertThat(expandFraction).isEqualTo(0f)
- val isScrollable by collectLastValue(appearanceViewModel.isScrollable)
+ val isScrollable by collectLastValue(scrollViewModel.isScrollable)
assertThat(isScrollable).isFalse()
fakeSceneDataSource.pause()
@@ -118,6 +131,7 @@
ObservableTransitionState.Transition(
fromScene = Scenes.Gone,
toScene = Scenes.Shade,
+ currentScene = flowOf(Scenes.Shade),
progress = transitionProgress,
isInitiatedByUserInput = false,
isUserInputOngoing = flowOf(false),
@@ -140,12 +154,12 @@
testScope.runTest {
val transitionState =
MutableStateFlow<ObservableTransitionState>(
- ObservableTransitionState.Idle(scene = Scenes.Lockscreen)
+ ObservableTransitionState.Idle(currentScene = Scenes.Lockscreen)
)
sceneInteractor.setTransitionState(transitionState)
- val expandFraction by collectLastValue(appearanceViewModel.expandFraction)
+ val expandFraction by collectLastValue(scrollViewModel.expandFraction)
assertThat(expandFraction).isEqualTo(1f)
- val isScrollable by collectLastValue(appearanceViewModel.isScrollable)
+ val isScrollable by collectLastValue(scrollViewModel.isScrollable)
assertThat(isScrollable).isFalse()
}
@@ -154,14 +168,14 @@
testScope.runTest {
val transitionState =
MutableStateFlow<ObservableTransitionState>(
- ObservableTransitionState.Idle(scene = Scenes.Shade)
+ ObservableTransitionState.Idle(currentScene = Scenes.Shade)
)
sceneInteractor.setTransitionState(transitionState)
- val expandFraction by collectLastValue(appearanceViewModel.expandFraction)
+ val expandFraction by collectLastValue(scrollViewModel.expandFraction)
assertThat(expandFraction).isEqualTo(1f)
fakeSceneDataSource.changeScene(toScene = Scenes.Shade)
- val isScrollable by collectLastValue(appearanceViewModel.isScrollable)
+ val isScrollable by collectLastValue(scrollViewModel.isScrollable)
assertThat(isScrollable).isTrue()
fakeSceneDataSource.pause()
@@ -172,6 +186,7 @@
ObservableTransitionState.Transition(
fromScene = Scenes.Shade,
toScene = Scenes.QuickSettings,
+ currentScene = flowOf(Scenes.QuickSettings),
progress = transitionProgress,
isInitiatedByUserInput = false,
isUserInputOngoing = flowOf(false),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModelTest.kt
similarity index 76%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModelTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModelTest.kt
index 78b7615..cbbc4d8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModelTest.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,116 +18,92 @@
import android.graphics.Rect
import android.graphics.drawable.Icon
-import androidx.test.ext.junit.runners.AndroidJUnit4
+import android.platform.test.flag.junit.FlagsParameterization
import androidx.test.filters.SmallTest
-import com.android.systemui.SysUITestComponent
-import com.android.systemui.SysUITestModule
import com.android.systemui.SysuiTestCase
-import com.android.systemui.TestMocksModule
-import com.android.systemui.biometrics.domain.BiometricsDomainLayerModule
-import com.android.systemui.collectLastValue
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.flags.FakeFeatureFlagsClassicModule
-import com.android.systemui.flags.Flags
-import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
-import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.flags.andSceneContainer
+import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
+import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
import com.android.systemui.keyguard.shared.model.DozeStateModel
import com.android.systemui.keyguard.shared.model.DozeTransitionModel
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.TransitionStep
+import com.android.systemui.kosmos.testScope
import com.android.systemui.plugins.DarkIconDispatcher
-import com.android.systemui.power.data.repository.FakePowerRepository
+import com.android.systemui.power.data.repository.fakePowerRepository
import com.android.systemui.power.shared.model.WakeSleepReason
import com.android.systemui.power.shared.model.WakefulnessState
-import com.android.systemui.runCurrent
-import com.android.systemui.runTest
-import com.android.systemui.shade.data.repository.FakeShadeRepository
+import com.android.systemui.shade.shadeTestUtil
import com.android.systemui.statusbar.notification.data.model.activeNotificationModel
-import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationListRepository
import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationsStore
-import com.android.systemui.statusbar.notification.data.repository.HeadsUpNotificationIconViewStateRepository
-import com.android.systemui.statusbar.phone.DozeParameters
+import com.android.systemui.statusbar.notification.data.repository.activeNotificationListRepository
+import com.android.systemui.statusbar.notification.data.repository.headsUpNotificationIconViewStateRepository
import com.android.systemui.statusbar.phone.SysuiDarkIconDispatcher
-import com.android.systemui.statusbar.phone.data.repository.FakeDarkIconRepository
-import com.android.systemui.statusbar.policy.data.repository.FakeDeviceProvisioningRepository
-import com.android.systemui.user.domain.UserDomainLayerModule
+import com.android.systemui.statusbar.phone.data.repository.fakeDarkIconRepository
+import com.android.systemui.statusbar.phone.dozeParameters
+import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.ui.isAnimating
import com.android.systemui.util.ui.value
import com.google.common.truth.Truth.assertThat
-import dagger.BindsInstance
-import dagger.Component
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4
+import platform.test.runner.parameterized.Parameters
@SmallTest
-@RunWith(AndroidJUnit4::class)
-class NotificationIconContainerStatusBarViewModelTest : SysuiTestCase() {
+@RunWith(ParameterizedAndroidJunit4::class)
+class NotificationIconContainerStatusBarViewModelTest(flags: FlagsParameterization?) :
+ SysuiTestCase() {
- @SysUISingleton
- @Component(
- modules =
- [
- SysUITestModule::class,
- BiometricsDomainLayerModule::class,
- UserDomainLayerModule::class,
- ]
- )
- interface TestComponent : SysUITestComponent<NotificationIconContainerStatusBarViewModel> {
-
- val activeNotificationsRepository: ActiveNotificationListRepository
- val darkIconRepository: FakeDarkIconRepository
- val deviceProvisioningRepository: FakeDeviceProvisioningRepository
- val headsUpViewStateRepository: HeadsUpNotificationIconViewStateRepository
- val keyguardTransitionRepository: FakeKeyguardTransitionRepository
- val keyguardRepository: FakeKeyguardRepository
- val powerRepository: FakePowerRepository
- val shadeRepository: FakeShadeRepository
-
- @Component.Factory
- interface Factory {
- fun create(
- @BindsInstance test: SysuiTestCase,
- mocks: TestMocksModule,
- featureFlags: FakeFeatureFlagsClassicModule,
- ): TestComponent
+ companion object {
+ @JvmStatic
+ @Parameters(name = "{0}")
+ fun getParams(): List<FlagsParameterization> {
+ return FlagsParameterization.allCombinationsOf().andSceneContainer()
}
}
- private val dozeParams: DozeParameters = mock()
+ init {
+ mSetFlagsRule.setFlagsParameterization(flags!!)
+ }
- private val testComponent: TestComponent =
- DaggerNotificationIconContainerStatusBarViewModelTest_TestComponent.factory()
- .create(
- test = this,
- featureFlags =
- FakeFeatureFlagsClassicModule {
- set(Flags.FULL_SCREEN_USER_SWITCHER, value = false)
- },
- mocks =
- TestMocksModule(
- dozeParameters = dozeParams,
- ),
- )
+ private val kosmos = testKosmos()
+ private val testScope = kosmos.testScope
+
+ private val keyguardRepository = kosmos.fakeKeyguardRepository
+ private val powerRepository = kosmos.fakePowerRepository
+ private val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository
+ private val darkIconRepository = kosmos.fakeDarkIconRepository
+ private val headsUpViewStateRepository = kosmos.headsUpNotificationIconViewStateRepository
+ private val activeNotificationsRepository = kosmos.activeNotificationListRepository
+
+ private val shadeTestUtil by lazy { kosmos.shadeTestUtil }
+
+ private val dozeParams = kosmos.dozeParameters
+
+ lateinit var underTest: NotificationIconContainerStatusBarViewModel
@Before
fun setup() {
- testComponent.apply {
- keyguardRepository.setKeyguardShowing(false)
- powerRepository.updateWakefulness(
- rawState = WakefulnessState.AWAKE,
- lastWakeReason = WakeSleepReason.OTHER,
- lastSleepReason = WakeSleepReason.OTHER,
- )
- }
+ underTest = kosmos.notificationIconContainerStatusBarViewModel
+ keyguardRepository.setKeyguardShowing(false)
+ powerRepository.updateWakefulness(
+ rawState = WakefulnessState.AWAKE,
+ lastWakeReason = WakeSleepReason.OTHER,
+ lastSleepReason = WakeSleepReason.OTHER,
+ )
}
@Test
fun animationsEnabled_isFalse_whenDeviceAsleepAndNotPulsing() =
- testComponent.runTest {
+ testScope.runTest {
powerRepository.updateWakefulness(
rawState = WakefulnessState.ASLEEP,
lastWakeReason = WakeSleepReason.POWER_BUTTON,
@@ -150,7 +126,7 @@
@Test
fun animationsEnabled_isTrue_whenDeviceAsleepAndPulsing() =
- testComponent.runTest {
+ testScope.runTest {
powerRepository.updateWakefulness(
rawState = WakefulnessState.ASLEEP,
lastWakeReason = WakeSleepReason.POWER_BUTTON,
@@ -173,7 +149,7 @@
@Test
fun animationsEnabled_isFalse_whenStartingToSleepAndNotControlScreenOff() =
- testComponent.runTest {
+ testScope.runTest {
powerRepository.updateWakefulness(
rawState = WakefulnessState.STARTING_TO_SLEEP,
lastWakeReason = WakeSleepReason.POWER_BUTTON,
@@ -194,7 +170,7 @@
@Test
fun animationsEnabled_isTrue_whenStartingToSleepAndControlScreenOff() =
- testComponent.runTest {
+ testScope.runTest {
val animationsEnabled by collectLastValue(underTest.animationsEnabled)
assertThat(animationsEnabled).isTrue()
@@ -218,7 +194,7 @@
@Test
fun animationsEnabled_isTrue_whenNotAsleep() =
- testComponent.runTest {
+ testScope.runTest {
powerRepository.updateWakefulness(
rawState = WakefulnessState.AWAKE,
lastWakeReason = WakeSleepReason.POWER_BUTTON,
@@ -236,7 +212,7 @@
@Test
fun animationsEnabled_isTrue_whenKeyguardIsNotShowing() =
- testComponent.runTest {
+ testScope.runTest {
val animationsEnabled by collectLastValue(underTest.animationsEnabled)
keyguardTransitionRepository.sendTransitionStep(
@@ -257,7 +233,7 @@
@Test
fun iconColors_testsDarkBounds() =
- testComponent.runTest {
+ testScope.runTest {
darkIconRepository.darkState.value =
SysuiDarkIconDispatcher.DarkChange(
emptyList(),
@@ -280,7 +256,7 @@
@Test
fun iconColors_staticDrawableColor_notInDarkTintArea() =
- testComponent.runTest {
+ testScope.runTest {
darkIconRepository.darkState.value =
SysuiDarkIconDispatcher.DarkChange(
listOf(Rect(0, 0, 5, 5)),
@@ -295,7 +271,7 @@
@Test
fun iconColors_notInDarkTintArea() =
- testComponent.runTest {
+ testScope.runTest {
darkIconRepository.darkState.value =
SysuiDarkIconDispatcher.DarkChange(
listOf(Rect(0, 0, 5, 5)),
@@ -309,9 +285,9 @@
@Test
fun isolatedIcon_animateOnAppear_shadeCollapsed() =
- testComponent.runTest {
+ testScope.runTest {
val icon: Icon = mock()
- shadeRepository.setLegacyShadeExpansion(0f)
+ shadeTestUtil.setShadeExpansion(0f)
activeNotificationsRepository.activeNotifications.value =
ActiveNotificationsStore.Builder()
.apply {
@@ -336,9 +312,9 @@
@Test
fun isolatedIcon_dontAnimateOnAppear_shadeExpanded() =
- testComponent.runTest {
+ testScope.runTest {
val icon: Icon = mock()
- shadeRepository.setLegacyShadeExpansion(.5f)
+ shadeTestUtil.setShadeExpansion(.5f)
activeNotificationsRepository.activeNotifications.value =
ActiveNotificationsStore.Builder()
.apply {
@@ -363,7 +339,7 @@
@Test
fun isolatedIcon_updateWhenIconDataChanges() =
- testComponent.runTest {
+ testScope.runTest {
val icon: Icon = mock()
val isolatedIcon by collectLastValue(underTest.isolatedIcon)
runCurrent()
@@ -390,7 +366,7 @@
@Test
fun isolatedIcon_lastMessageIsFromReply_notNull() =
- testComponent.runTest {
+ testScope.runTest {
val icon: Icon = mock()
headsUpViewStateRepository.isolatedNotification.value = "notif1"
activeNotificationsRepository.activeNotifications.value =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/domain/interactor/SharedNotificationContainerInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/domain/interactor/SharedNotificationContainerInteractorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/domain/interactor/SharedNotificationContainerInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/domain/interactor/SharedNotificationContainerInteractorTest.kt
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt
index 3408e06..2cd295c 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt
@@ -61,6 +61,7 @@
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.advanceTimeBy
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
@@ -654,7 +655,7 @@
var notificationCount = 10
val calculateSpace = { space: Float, useExtraShelfSpace: Boolean -> notificationCount }
val maxNotifications by collectLastValue(underTest.getMaxNotifications(calculateSpace))
-
+ advanceTimeBy(50L)
showLockscreen()
overrideResource(R.bool.config_use_split_notification_shade, false)
@@ -668,12 +669,14 @@
// Also updates when directly requested (as it would from NotificationStackScrollLayout)
notificationCount = 25
sharedNotificationContainerInteractor.notificationStackChanged()
+ advanceTimeBy(50L)
assertThat(maxNotifications).isEqualTo(25)
// Also ensure another collection starts with the same value. As an example, folding
// then unfolding will restart the coroutine and it must get the last value immediately.
val newMaxNotifications by
collectLastValue(underTest.getMaxNotifications(calculateSpace))
+ advanceTimeBy(50L)
assertThat(newMaxNotifications).isEqualTo(25)
}
@@ -683,7 +686,7 @@
var notificationCount = 10
val calculateSpace = { space: Float, useExtraShelfSpace: Boolean -> notificationCount }
val maxNotifications by collectLastValue(underTest.getMaxNotifications(calculateSpace))
-
+ advanceTimeBy(50L)
showLockscreen()
overrideResource(R.bool.config_use_split_notification_shade, false)
@@ -718,6 +721,7 @@
testScope.runTest {
val calculateSpace = { space: Float, useExtraShelfSpace: Boolean -> 10 }
val maxNotifications by collectLastValue(underTest.getMaxNotifications(calculateSpace))
+ advanceTimeBy(50L)
// Show lockscreen with shade expanded
showLockscreenWithShadeExpanded()
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ActivityStarterImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ActivityStarterImplTest.kt
index 1501d9c..b643968 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ActivityStarterImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ActivityStarterImplTest.kt
@@ -30,7 +30,6 @@
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.Mockito.mock
-import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImplTest.kt
index b443489..0ca6207 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImplTest.kt
@@ -259,7 +259,7 @@
underTest.dismissKeyguardThenExecute({ true }, {}, false)
verify(biometricUnlockController)
- .startWakeAndUnlock(BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING)
+ .startWakeAndUnlock(BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING, null)
}
@Test
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/util/kotlin/BooleanFlowOperatorsTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/util/kotlin/BooleanFlowOperatorsTest.kt
index 03a39f8..2d8cd93 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/util/kotlin/BooleanFlowOperatorsTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/util/kotlin/BooleanFlowOperatorsTest.kt
@@ -23,9 +23,9 @@
import com.android.systemui.coroutines.collectValues
import com.android.systemui.kosmos.testScope
import com.android.systemui.testKosmos
-import com.android.systemui.util.kotlin.BooleanFlowOperators.and
+import com.android.systemui.util.kotlin.BooleanFlowOperators.allOf
+import com.android.systemui.util.kotlin.BooleanFlowOperators.anyOf
import com.android.systemui.util.kotlin.BooleanFlowOperators.not
-import com.android.systemui.util.kotlin.BooleanFlowOperators.or
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
@@ -45,21 +45,21 @@
@Test
fun and_allTrue_returnsTrue() =
testScope.runTest {
- val result by collectLastValue(and(TRUE, TRUE))
+ val result by collectLastValue(allOf(TRUE, TRUE))
assertThat(result).isTrue()
}
@Test
fun and_anyFalse_returnsFalse() =
testScope.runTest {
- val result by collectLastValue(and(TRUE, FALSE, TRUE))
+ val result by collectLastValue(allOf(TRUE, FALSE, TRUE))
assertThat(result).isFalse()
}
@Test
fun and_allFalse_returnsFalse() =
testScope.runTest {
- val result by collectLastValue(and(FALSE, FALSE, FALSE))
+ val result by collectLastValue(allOf(FALSE, FALSE, FALSE))
assertThat(result).isFalse()
}
@@ -68,7 +68,7 @@
testScope.runTest {
val flow1 = MutableStateFlow(false)
val flow2 = MutableStateFlow(false)
- val values by collectValues(and(flow1, flow2))
+ val values by collectValues(allOf(flow1, flow2))
assertThat(values).containsExactly(false)
flow1.value = true
@@ -81,21 +81,21 @@
@Test
fun or_allTrue_returnsTrue() =
testScope.runTest {
- val result by collectLastValue(or(TRUE, TRUE))
+ val result by collectLastValue(anyOf(TRUE, TRUE))
assertThat(result).isTrue()
}
@Test
fun or_anyTrue_returnsTrue() =
testScope.runTest {
- val result by collectLastValue(or(FALSE, TRUE, FALSE))
+ val result by collectLastValue(anyOf(FALSE, TRUE, FALSE))
assertThat(result).isTrue()
}
@Test
fun or_allFalse_returnsFalse() =
testScope.runTest {
- val result by collectLastValue(or(FALSE, FALSE, FALSE))
+ val result by collectLastValue(anyOf(FALSE, FALSE, FALSE))
assertThat(result).isFalse()
}
@@ -104,7 +104,7 @@
testScope.runTest {
val flow1 = MutableStateFlow(false)
val flow2 = MutableStateFlow(false)
- val values by collectValues(or(flow1, flow2))
+ val values by collectValues(anyOf(flow1, flow2))
assertThat(values).containsExactly(false)
flow1.value = true
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractorTest.kt
index 632196c..2af2602 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractorTest.kt
@@ -21,6 +21,7 @@
import android.media.AudioDeviceInfo
import android.media.AudioDevicePort
import android.media.AudioManager
+import android.testing.TestableLooper
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.settingslib.R
@@ -54,6 +55,7 @@
@OptIn(ExperimentalCoroutinesApi::class)
@RunWith(AndroidJUnit4::class)
@SmallTest
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
class AudioOutputInteractorTest : SysuiTestCase() {
private val kosmos = testKosmos()
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/anc/data/repository/AncSliceRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/anc/data/repository/AncSliceRepositoryTest.kt
index dc96139..dddf582 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/anc/data/repository/AncSliceRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/anc/data/repository/AncSliceRepositoryTest.kt
@@ -61,6 +61,7 @@
AncSliceRepositoryImpl(
localMediaRepositoryFactory,
testScope.testScheduler,
+ testScope.testScheduler,
sliceViewManager,
)
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/domain/MediaOutputAvailabilityCriteriaTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/domain/MediaOutputAvailabilityCriteriaTest.kt
deleted file mode 100644
index 96b4dae..0000000
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/domain/MediaOutputAvailabilityCriteriaTest.kt
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.volume.panel.component.mediaoutput.domain
-
-import android.media.AudioManager
-import android.testing.TestableLooper.RunWithLooper
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.kosmos.testScope
-import com.android.systemui.testKosmos
-import com.android.systemui.volume.data.repository.audioRepository
-import com.android.systemui.volume.domain.interactor.audioModeInteractor
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.runCurrent
-import kotlinx.coroutines.test.runTest
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@OptIn(ExperimentalCoroutinesApi::class)
-@SmallTest
-@RunWith(AndroidJUnit4::class)
-@RunWithLooper(setAsMainLooper = true)
-class MediaOutputAvailabilityCriteriaTest : SysuiTestCase() {
-
- private val kosmos = testKosmos()
-
- private lateinit var underTest: MediaOutputAvailabilityCriteria
-
- @Before
- fun setup() {
- underTest =
- MediaOutputAvailabilityCriteria(
- kosmos.audioModeInteractor,
- )
- }
-
- @Test
- fun notInCall_isAvailable_true() {
- with(kosmos) {
- testScope.runTest {
- audioRepository.setMode(AudioManager.MODE_NORMAL)
-
- val isAvailable by collectLastValue(underTest.isAvailable())
- runCurrent()
-
- assertThat(isAvailable).isTrue()
- }
- }
- }
-
- @Test
- fun inCall_isAvailable_false() {
- with(kosmos) {
- testScope.runTest {
- audioRepository.setMode(AudioManager.MODE_IN_CALL)
-
- val isAvailable by collectLastValue(underTest.isAvailable())
- runCurrent()
-
- assertThat(isAvailable).isFalse()
- }
- }
- }
-}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaDeviceSessionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaDeviceSessionInteractorTest.kt
index b5c5809..64c9429 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaDeviceSessionInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaDeviceSessionInteractorTest.kt
@@ -28,6 +28,7 @@
import com.android.systemui.volume.localMediaController
import com.android.systemui.volume.mediaControllerRepository
import com.android.systemui.volume.mediaOutputInteractor
+import com.android.systemui.volume.panel.shared.model.filterData
import com.android.systemui.volume.remoteMediaController
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -67,7 +68,8 @@
fun playbackInfo_returnsPlaybackInfo() {
with(kosmos) {
testScope.runTest {
- val session by collectLastValue(mediaOutputInteractor.defaultActiveMediaSession)
+ val session by
+ collectLastValue(mediaOutputInteractor.defaultActiveMediaSession.filterData())
runCurrent()
val info by collectLastValue(underTest.playbackInfo(session!!))
runCurrent()
@@ -81,7 +83,8 @@
fun playbackState_returnsPlaybackState() {
with(kosmos) {
testScope.runTest {
- val session by collectLastValue(mediaOutputInteractor.defaultActiveMediaSession)
+ val session by
+ collectLastValue(mediaOutputInteractor.defaultActiveMediaSession.filterData())
runCurrent()
val state by collectLastValue(underTest.playbackState(session!!))
runCurrent()
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputInteractorTest.kt
new file mode 100644
index 0000000..9e86ced
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputInteractorTest.kt
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.volume.panel.component.mediaoutput.domain.interactor
+
+import android.media.AudioAttributes
+import android.media.VolumeProvider
+import android.media.session.MediaController
+import android.media.session.PlaybackState
+import android.testing.TestableLooper
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.testKosmos
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
+import com.android.systemui.volume.data.repository.FakeLocalMediaRepository
+import com.android.systemui.volume.localMediaController
+import com.android.systemui.volume.localMediaRepositoryFactory
+import com.android.systemui.volume.localPlaybackInfo
+import com.android.systemui.volume.localPlaybackStateBuilder
+import com.android.systemui.volume.mediaControllerRepository
+import com.android.systemui.volume.mediaOutputInteractor
+import com.android.systemui.volume.panel.component.mediaoutput.shared.model.MediaDeviceSession
+import com.android.systemui.volume.panel.shared.model.Result
+import com.android.systemui.volume.remoteMediaController
+import com.android.systemui.volume.remotePlaybackInfo
+import com.android.systemui.volume.remotePlaybackStateBuilder
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+class MediaOutputInteractorTest : SysuiTestCase() {
+
+ private val kosmos = testKosmos()
+
+ private lateinit var underTest: MediaOutputInteractor
+
+ @Before
+ fun setUp() =
+ with(kosmos) {
+ localMediaRepositoryFactory.setLocalMediaRepository(
+ "local.test.pkg",
+ FakeLocalMediaRepository().apply {
+ updateCurrentConnectedDevice(
+ mock { whenever(name).thenReturn("local_media_device") }
+ )
+ },
+ )
+ localMediaRepositoryFactory.setLocalMediaRepository(
+ "remote.test.pkg",
+ FakeLocalMediaRepository().apply {
+ updateCurrentConnectedDevice(
+ mock { whenever(name).thenReturn("remote_media_device") }
+ )
+ },
+ )
+
+ underTest = kosmos.mediaOutputInteractor
+ }
+
+ @Test
+ fun noActiveMediaDeviceSessions_nulls() =
+ with(kosmos) {
+ testScope.runTest {
+ mediaControllerRepository.setActiveSessions(emptyList())
+
+ val activeMediaDeviceSessions by
+ collectLastValue(underTest.activeMediaDeviceSessions)
+ runCurrent()
+
+ assertThat(activeMediaDeviceSessions!!.local).isNull()
+ assertThat(activeMediaDeviceSessions!!.remote).isNull()
+ }
+ }
+
+ @Test
+ fun activeMediaDeviceSessions_areParsed() =
+ with(kosmos) {
+ testScope.runTest {
+ mediaControllerRepository.setActiveSessions(
+ listOf(localMediaController, remoteMediaController)
+ )
+
+ val activeMediaDeviceSessions by
+ collectLastValue(underTest.activeMediaDeviceSessions)
+ runCurrent()
+
+ with(activeMediaDeviceSessions!!.local!!) {
+ assertThat(packageName).isEqualTo("local.test.pkg")
+ assertThat(appLabel).isEqualTo("local_media_controller_label")
+ assertThat(canAdjustVolume).isTrue()
+ }
+ with(activeMediaDeviceSessions!!.remote!!) {
+ assertThat(packageName).isEqualTo("remote.test.pkg")
+ assertThat(appLabel).isEqualTo("remote_media_controller_label")
+ assertThat(canAdjustVolume).isTrue()
+ }
+ }
+ }
+
+ @Test
+ fun activeMediaDeviceSessions_volumeControlFixed_cantAdjustVolume() =
+ with(kosmos) {
+ testScope.runTest {
+ localPlaybackInfo =
+ MediaController.PlaybackInfo(
+ MediaController.PlaybackInfo.PLAYBACK_TYPE_LOCAL,
+ VolumeProvider.VOLUME_CONTROL_FIXED,
+ 0,
+ 0,
+ AudioAttributes.Builder().build(),
+ "",
+ )
+ remotePlaybackInfo =
+ MediaController.PlaybackInfo(
+ MediaController.PlaybackInfo.PLAYBACK_TYPE_REMOTE,
+ VolumeProvider.VOLUME_CONTROL_FIXED,
+ 0,
+ 0,
+ AudioAttributes.Builder().build(),
+ "",
+ )
+ mediaControllerRepository.setActiveSessions(
+ listOf(localMediaController, remoteMediaController)
+ )
+
+ val activeMediaDeviceSessions by
+ collectLastValue(underTest.activeMediaDeviceSessions)
+ runCurrent()
+
+ assertThat(activeMediaDeviceSessions!!.local!!.canAdjustVolume).isFalse()
+ assertThat(activeMediaDeviceSessions!!.remote!!.canAdjustVolume).isFalse()
+ }
+ }
+
+ @Test
+ fun activeLocalAndRemoteSession_defaultSession_local() =
+ with(kosmos) {
+ testScope.runTest {
+ localPlaybackStateBuilder.setState(PlaybackState.STATE_PLAYING, 0, 0f)
+ remotePlaybackStateBuilder.setState(PlaybackState.STATE_PLAYING, 0, 0f)
+ mediaControllerRepository.setActiveSessions(
+ listOf(localMediaController, remoteMediaController)
+ )
+
+ val defaultActiveMediaSession by
+ collectLastValue(underTest.defaultActiveMediaSession)
+ val currentDevice by collectLastValue(underTest.currentConnectedDevice)
+ runCurrent()
+
+ with((defaultActiveMediaSession as Result.Data<MediaDeviceSession?>).data!!) {
+ assertThat(packageName).isEqualTo("local.test.pkg")
+ assertThat(appLabel).isEqualTo("local_media_controller_label")
+ assertThat(canAdjustVolume).isTrue()
+ }
+ assertThat(currentDevice!!.name).isEqualTo("local_media_device")
+ }
+ }
+
+ @Test
+ fun activeRemoteSession_defaultSession_remote() =
+ with(kosmos) {
+ testScope.runTest {
+ localPlaybackStateBuilder.setState(PlaybackState.STATE_PAUSED, 0, 0f)
+ remotePlaybackStateBuilder.setState(PlaybackState.STATE_PLAYING, 0, 0f)
+ mediaControllerRepository.setActiveSessions(
+ listOf(localMediaController, remoteMediaController)
+ )
+
+ val defaultActiveMediaSession by
+ collectLastValue(underTest.defaultActiveMediaSession)
+ val currentDevice by collectLastValue(underTest.currentConnectedDevice)
+ runCurrent()
+
+ with((defaultActiveMediaSession as Result.Data<MediaDeviceSession?>).data!!) {
+ assertThat(packageName).isEqualTo("remote.test.pkg")
+ assertThat(appLabel).isEqualTo("remote_media_controller_label")
+ assertThat(canAdjustVolume).isTrue()
+ }
+ assertThat(currentDevice!!.name).isEqualTo("remote_media_device")
+ }
+ }
+
+ @Test
+ fun inactiveLocalAndRemoteSession_defaultSession_local() =
+ with(kosmos) {
+ testScope.runTest {
+ localPlaybackStateBuilder.setState(PlaybackState.STATE_PAUSED, 0, 0f)
+ remotePlaybackStateBuilder.setState(PlaybackState.STATE_PAUSED, 0, 0f)
+ mediaControllerRepository.setActiveSessions(
+ listOf(localMediaController, remoteMediaController)
+ )
+
+ val defaultActiveMediaSession by
+ collectLastValue(underTest.defaultActiveMediaSession)
+ val currentDevice by collectLastValue(underTest.currentConnectedDevice)
+ runCurrent()
+
+ with((defaultActiveMediaSession as Result.Data<MediaDeviceSession?>).data!!) {
+ assertThat(packageName).isEqualTo("local.test.pkg")
+ assertThat(appLabel).isEqualTo("local_media_controller_label")
+ assertThat(canAdjustVolume).isTrue()
+ }
+ assertThat(currentDevice!!.name).isEqualTo("local_media_device")
+ }
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModelTest.kt
index 30524d9..49f82d4 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModelTest.kt
@@ -30,6 +30,8 @@
import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
+import com.android.systemui.volume.domain.interactor.audioModeInteractor
+import com.android.systemui.volume.domain.interactor.audioOutputInteractor
import com.android.systemui.volume.localMediaController
import com.android.systemui.volume.localMediaRepository
import com.android.systemui.volume.mediaControllerRepository
@@ -64,6 +66,8 @@
testScope.backgroundScope,
mediaOutputActionsInteractor,
mediaDeviceSessionInteractor,
+ audioOutputInteractor,
+ audioModeInteractor,
mediaOutputInteractor,
uiEventLogger,
)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/wmshell/WMShellTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/wmshell/WMShellTest.kt
index 55e46dc..e1be6b0 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/wmshell/WMShellTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/wmshell/WMShellTest.kt
@@ -24,16 +24,17 @@
import com.android.keyguard.keyguardUpdateMonitor
import com.android.systemui.Flags.FLAG_COMMUNAL_HUB
import com.android.systemui.SysuiTestCase
+import com.android.systemui.communal.domain.interactor.setCommunalAvailable
import com.android.systemui.communal.ui.viewmodel.communalTransitionViewModel
import com.android.systemui.communal.util.fakeCommunalColors
import com.android.systemui.concurrency.fakeExecutor
-import com.android.systemui.dock.DockManager
-import com.android.systemui.dock.fakeDockManager
import com.android.systemui.flags.Flags.COMMUNAL_SERVICE_ENABLED
import com.android.systemui.flags.fakeFeatureFlagsClassic
import com.android.systemui.keyguard.ScreenLifecycle
import com.android.systemui.keyguard.WakefulnessLifecycle
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
+import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
+import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.wakefulnessLifecycle
import com.android.systemui.kosmos.testScope
import com.android.systemui.model.SysUiState
@@ -63,7 +64,6 @@
import java.util.Optional
import java.util.concurrent.Executor
import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
@@ -186,29 +186,18 @@
verify(mRecentTasks).setTransitionBackgroundColor(null)
verify(mRecentTasks, never()).setTransitionBackgroundColor(black)
- setDocked(true)
- // Make communal available
- kosmos.fakeKeyguardRepository.setIsEncryptedOrLockdown(false)
- kosmos.fakeUserRepository.setSelectedUserInfo(MAIN_USER_INFO)
- kosmos.fakeKeyguardRepository.setKeyguardShowing(true)
-
+ // Transition to occluded from the glanceable hub.
+ kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps(
+ from = KeyguardState.GLANCEABLE_HUB,
+ to = KeyguardState.OCCLUDED,
+ testScope
+ )
+ kosmos.setCommunalAvailable(true)
runCurrent()
verify(mRecentTasks).setTransitionBackgroundColor(black)
}
- private fun TestScope.setDocked(docked: Boolean) {
- kosmos.fakeDockManager.setIsDocked(docked)
- val event =
- if (docked) {
- DockManager.STATE_DOCKED
- } else {
- DockManager.STATE_NONE
- }
- kosmos.fakeDockManager.setDockEvent(event)
- runCurrent()
- }
-
private companion object {
val MAIN_USER_INFO = UserInfo(0, "primary", UserInfo.FLAG_MAIN)
}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java
index c9e2989..d13c750 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java
@@ -21,11 +21,11 @@
import android.metrics.LogMaker;
import android.service.quicksettings.Tile;
import android.text.TextUtils;
-import android.view.View;
import androidx.annotation.Nullable;
import com.android.internal.logging.InstanceId;
+import com.android.systemui.animation.Expandable;
import com.android.systemui.plugins.annotations.DependsOn;
import com.android.systemui.plugins.annotations.ProvidesInterface;
import com.android.systemui.plugins.qs.QSTile.Callback;
@@ -58,23 +58,23 @@
/**
* The tile was clicked.
*
- * @param view The view that was clicked.
+ * @param expandable {@link Expandable} that was clicked.
*/
- void click(@Nullable View view);
+ void click(@Nullable Expandable expandable);
/**
* The tile secondary click was triggered.
*
- * @param view The view that was clicked.
+ * @param expandable {@link Expandable} that was clicked.
*/
- void secondaryClick(@Nullable View view);
+ void secondaryClick(@Nullable Expandable expandable);
/**
* The tile was long clicked.
*
- * @param view The view that was clicked.
+ * @param expandable {@link Expandable} that was clicked.
*/
- void longClick(@Nullable View view);
+ void longClick(@Nullable Expandable expandable);
void userSwitch(int currentUser);
diff --git a/packages/SystemUI/res-keyguard/values-am/strings.xml b/packages/SystemUI/res-keyguard/values-am/strings.xml
index b62e684b..b35259a 100644
--- a/packages/SystemUI/res-keyguard/values-am/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-am/strings.xml
@@ -23,7 +23,7 @@
<string name="keyguard_enter_your_pin" msgid="5429932527814874032">"የእርስዎን ፒን ያስገቡ"</string>
<string name="keyguard_enter_pin" msgid="8114529922480276834">"ፒን ያስገቡ"</string>
<string name="keyguard_enter_your_pattern" msgid="351503370332324745">"ሥርዓተ-ጥለትዎን ያስገቡ"</string>
- <string name="keyguard_enter_pattern" msgid="7616595160901084119">"ስርዓተ ጥለት ይሳሉ"</string>
+ <string name="keyguard_enter_pattern" msgid="7616595160901084119">"ሥርዓተ ጥለት ይሳሉ"</string>
<string name="keyguard_enter_your_password" msgid="7225626204122735501">"ይለፍ ቃልዎን ያስገቡ"</string>
<string name="keyguard_enter_password" msgid="6483623792371009758">"የይለፍ ቃል ያስገቡ"</string>
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"ልክ ያልሆነ ካርድ።"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ar/strings.xml b/packages/SystemUI/res-keyguard/values-ar/strings.xml
index 427373d..b419880 100644
--- a/packages/SystemUI/res-keyguard/values-ar/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ar/strings.xml
@@ -23,9 +23,9 @@
<string name="keyguard_enter_your_pin" msgid="5429932527814874032">"أدخل رقم التعريف الشخصي (PIN)"</string>
<string name="keyguard_enter_pin" msgid="8114529922480276834">"أدخِل رقم التعريف الشخصي"</string>
<string name="keyguard_enter_your_pattern" msgid="351503370332324745">"أدخل النقش"</string>
- <string name="keyguard_enter_pattern" msgid="7616595160901084119">"ارسم النقش."</string>
+ <string name="keyguard_enter_pattern" msgid="7616595160901084119">"ارسم النقش"</string>
<string name="keyguard_enter_your_password" msgid="7225626204122735501">"أدخل كلمة المرور"</string>
- <string name="keyguard_enter_password" msgid="6483623792371009758">"أدخِل كلمة المرور."</string>
+ <string name="keyguard_enter_password" msgid="6483623792371009758">"أدخِل كلمة المرور"</string>
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"بطاقة غير صالحة."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"اكتمل الشحن"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • جارٍ الشحن لاسلكيًا"</string>
@@ -57,11 +57,11 @@
<string name="kg_wrong_pin" msgid="4160978845968732624">"رقم تعريف شخصي خاطئ"</string>
<string name="kg_wrong_pin_try_again" msgid="3129729383303430190">"لقد أدخلت رقم تعريف شخصي غير صحيح. يُرجى إعادة المحاولة."</string>
<string name="kg_wrong_input_try_fp_suggestion" msgid="3143861542242024833">"جرّب فتح القفل باستخدام بصمة الإصبع."</string>
- <string name="kg_fp_not_recognized" msgid="5183108260932029241">"لم يتم التعرّف على البصمة."</string>
+ <string name="kg_fp_not_recognized" msgid="5183108260932029241">"لم يتم التعرّف على البصمة"</string>
<string name="bouncer_face_not_recognized" msgid="1666128054475597485">"لم يتم التعرّف على الوجه."</string>
- <string name="kg_bio_try_again_or_pin" msgid="4752168242723808390">"يُرجى إعادة المحاولة أو إدخال رقم التعريف الشخصي."</string>
- <string name="kg_bio_try_again_or_password" msgid="1473132729225398039">"يُرجى إعادة المحاولة أو إدخال كلمة المرور."</string>
- <string name="kg_bio_try_again_or_pattern" msgid="4867893307468801501">"يُرجى إعادة المحاولة أو رسم النقش."</string>
+ <string name="kg_bio_try_again_or_pin" msgid="4752168242723808390">"يُرجى إعادة المحاولة أو إدخال رقم التعريف الشخصي"</string>
+ <string name="kg_bio_try_again_or_password" msgid="1473132729225398039">"يُرجى إعادة المحاولة أو إدخال كلمة المرور"</string>
+ <string name="kg_bio_try_again_or_pattern" msgid="4867893307468801501">"يُرجى إعادة المحاولة أو رسم النقش"</string>
<string name="kg_bio_too_many_attempts_pin" msgid="5850845723433047605">"يجب إدخال رقم PIN لأنّك أجريت محاولات كثيرة جدًا."</string>
<string name="kg_bio_too_many_attempts_password" msgid="5551690347827728042">"يجب إدخال كلمة المرور لأنك أجريت محاولات كثيرة جدًا."</string>
<string name="kg_bio_too_many_attempts_pattern" msgid="736884689355181602">"يجب رسم النقش لأنّك أجريت محاولات كثيرة جدًا."</string>
diff --git a/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml b/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml
index ee27e83..74b1fd3 100644
--- a/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml
@@ -57,7 +57,7 @@
<string name="kg_wrong_pin" msgid="4160978845968732624">"Pogrešan PIN"</string>
<string name="kg_wrong_pin_try_again" msgid="3129729383303430190">"Pogrešan PIN. Probajte ponovo."</string>
<string name="kg_wrong_input_try_fp_suggestion" msgid="3143861542242024833">"Ili otključajte otiskom prsta"</string>
- <string name="kg_fp_not_recognized" msgid="5183108260932029241">"Otisak prsta neprepoznat"</string>
+ <string name="kg_fp_not_recognized" msgid="5183108260932029241">"Otisak prsta nije prepoznat"</string>
<string name="bouncer_face_not_recognized" msgid="1666128054475597485">"Lice nije prepoznato"</string>
<string name="kg_bio_try_again_or_pin" msgid="4752168242723808390">"Probajte ponovo ili unesite PIN"</string>
<string name="kg_bio_try_again_or_password" msgid="1473132729225398039">"Probajte ponovo ili unesite lozinku"</string>
diff --git a/packages/SystemUI/res-keyguard/values-bn/strings.xml b/packages/SystemUI/res-keyguard/values-bn/strings.xml
index 5b804e2..fe6636b 100644
--- a/packages/SystemUI/res-keyguard/values-bn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-bn/strings.xml
@@ -23,7 +23,7 @@
<string name="keyguard_enter_your_pin" msgid="5429932527814874032">"পিন লিখুন"</string>
<string name="keyguard_enter_pin" msgid="8114529922480276834">"পিন লিখুন"</string>
<string name="keyguard_enter_your_pattern" msgid="351503370332324745">"প্যাটার্ন আঁকুন"</string>
- <string name="keyguard_enter_pattern" msgid="7616595160901084119">"প্যাটার্ন দিন"</string>
+ <string name="keyguard_enter_pattern" msgid="7616595160901084119">"প্যাটার্ন আঁকুন"</string>
<string name="keyguard_enter_your_password" msgid="7225626204122735501">"পাসওয়ার্ড লিখুন"</string>
<string name="keyguard_enter_password" msgid="6483623792371009758">"পাসওয়ার্ড লিখুন"</string>
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"ভুল কার্ড।"</string>
diff --git a/packages/SystemUI/res-keyguard/values-bs/strings.xml b/packages/SystemUI/res-keyguard/values-bs/strings.xml
index 4a5e789..baef51a 100644
--- a/packages/SystemUI/res-keyguard/values-bs/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-bs/strings.xml
@@ -23,7 +23,7 @@
<string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Unesite PIN"</string>
<string name="keyguard_enter_pin" msgid="8114529922480276834">"Unesite PIN"</string>
<string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Unesite uzorak"</string>
- <string name="keyguard_enter_pattern" msgid="7616595160901084119">"Unesite uzorak"</string>
+ <string name="keyguard_enter_pattern" msgid="7616595160901084119">"Nacrtajte uzorak"</string>
<string name="keyguard_enter_your_password" msgid="7225626204122735501">"Unesite lozinku"</string>
<string name="keyguard_enter_password" msgid="6483623792371009758">"Unesite lozinku"</string>
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Nevažeća kartica."</string>
@@ -126,8 +126,8 @@
<string name="keyguard_unlock_to_continue" msgid="7509503484250597743">"Otključajte uređaj da nastavite"</string>
<string name="kg_prompt_unattended_update_pin" msgid="5979434876768801873">"Unesite PIN da kasnije instalirate ažuriranje"</string>
<string name="kg_prompt_unattended_update_password" msgid="8805664437604967210">"Unesite lozinku da kasnije instalirate ažuriranje"</string>
- <string name="kg_prompt_unattended_update_pattern" msgid="8580479377489546091">"Unesite uzorak da kasnije instalirate ažuriranje"</string>
+ <string name="kg_prompt_unattended_update_pattern" msgid="8580479377489546091">"Nacrtajte uzorak da kasnije instalirate ažuriranje"</string>
<string name="kg_prompt_after_update_pin" msgid="7051709651908643013">"Uređaj je ažuriran. Unesite PIN da nastavite."</string>
<string name="kg_prompt_after_update_password" msgid="153703052501352094">"Uređaj je ažuriran. Unesite lozinku da nastavite."</string>
- <string name="kg_prompt_after_update_pattern" msgid="1484084551298241992">"Uređaj je ažuriran. Unesite uzorak da nastavite."</string>
+ <string name="kg_prompt_after_update_pattern" msgid="1484084551298241992">"Uređaj je ažuriran. Nacrtajte uzorak da nastavite."</string>
</resources>
diff --git a/packages/SystemUI/res-keyguard/values-fr/strings.xml b/packages/SystemUI/res-keyguard/values-fr/strings.xml
index 188a76a..822e16e 100644
--- a/packages/SystemUI/res-keyguard/values-fr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-fr/strings.xml
@@ -23,7 +23,7 @@
<string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Saisissez votre code"</string>
<string name="keyguard_enter_pin" msgid="8114529922480276834">"Saisissez le code"</string>
<string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Tracez votre schéma"</string>
- <string name="keyguard_enter_pattern" msgid="7616595160901084119">"Dessinez un schéma"</string>
+ <string name="keyguard_enter_pattern" msgid="7616595160901084119">"Dessinez le schéma"</string>
<string name="keyguard_enter_your_password" msgid="7225626204122735501">"Saisissez votre mot de passe"</string>
<string name="keyguard_enter_password" msgid="6483623792371009758">"Saisissez le mot de passe"</string>
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Carte non valide."</string>
diff --git a/packages/SystemUI/res-keyguard/values-gl/strings.xml b/packages/SystemUI/res-keyguard/values-gl/strings.xml
index e5cd788..26a4dc5 100644
--- a/packages/SystemUI/res-keyguard/values-gl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-gl/strings.xml
@@ -57,11 +57,11 @@
<string name="kg_wrong_pin" msgid="4160978845968732624">"PIN incorrecto"</string>
<string name="kg_wrong_pin_try_again" msgid="3129729383303430190">"PIN incorrecto. Téntao."</string>
<string name="kg_wrong_input_try_fp_suggestion" msgid="3143861542242024833">"Tamén podes desbloquealo coa impresión dixital"</string>
- <string name="kg_fp_not_recognized" msgid="5183108260932029241">"Impr. dixital non recoñec."</string>
+ <string name="kg_fp_not_recognized" msgid="5183108260932029241">"Impresión dixital non recoñecida"</string>
<string name="bouncer_face_not_recognized" msgid="1666128054475597485">"A cara non se recoñeceu"</string>
<string name="kg_bio_try_again_or_pin" msgid="4752168242723808390">"Téntao de novo ou pon o PIN"</string>
<string name="kg_bio_try_again_or_password" msgid="1473132729225398039">"Téntao de novo ou pon o contrasinal"</string>
- <string name="kg_bio_try_again_or_pattern" msgid="4867893307468801501">"Téntao de novo ou debuxa o contrasinal"</string>
+ <string name="kg_bio_try_again_or_pattern" msgid="4867893307468801501">"Téntao de novo ou debuxa o padrón"</string>
<string name="kg_bio_too_many_attempts_pin" msgid="5850845723433047605">"Requírese o PIN tras realizar demasiados intentos"</string>
<string name="kg_bio_too_many_attempts_password" msgid="5551690347827728042">"Requírese o contrasinal tras demasiados intentos"</string>
<string name="kg_bio_too_many_attempts_pattern" msgid="736884689355181602">"Requírese o padrón tras realizar demasiados intentos"</string>
diff --git a/packages/SystemUI/res-keyguard/values-hi/strings.xml b/packages/SystemUI/res-keyguard/values-hi/strings.xml
index 2b01903..d905581 100644
--- a/packages/SystemUI/res-keyguard/values-hi/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hi/strings.xml
@@ -57,11 +57,11 @@
<string name="kg_wrong_pin" msgid="4160978845968732624">"गलत पिन"</string>
<string name="kg_wrong_pin_try_again" msgid="3129729383303430190">"गलत पिन. दोबारा डालें."</string>
<string name="kg_wrong_input_try_fp_suggestion" msgid="3143861542242024833">"फ़िंगरप्रिंट से अनलॉक करें"</string>
- <string name="kg_fp_not_recognized" msgid="5183108260932029241">"फ़िंगरप्रिंट गलत है"</string>
+ <string name="kg_fp_not_recognized" msgid="5183108260932029241">"फ़िंगरप्रिंट की पहचान नहीं हो पाई"</string>
<string name="bouncer_face_not_recognized" msgid="1666128054475597485">"चेहरा नहीं पहचाना गया"</string>
<string name="kg_bio_try_again_or_pin" msgid="4752168242723808390">"फिर से कोशिश करें या पिन डालें"</string>
<string name="kg_bio_try_again_or_password" msgid="1473132729225398039">"फिर से कोशिश करें या पासवर्ड डालें"</string>
- <string name="kg_bio_try_again_or_pattern" msgid="4867893307468801501">"फिर से कोशिश करें या पैटर्न ड्रा करें"</string>
+ <string name="kg_bio_try_again_or_pattern" msgid="4867893307468801501">"फिर से कोशिश करें या पैटर्न ड्रॉ करें"</string>
<string name="kg_bio_too_many_attempts_pin" msgid="5850845723433047605">"कई बार कोशिश की जा चुकी है, इसलिए पिन डालें"</string>
<string name="kg_bio_too_many_attempts_password" msgid="5551690347827728042">"कई बार कोशिश की जा चुकी है, इसलिए पासवर्ड डालें"</string>
<string name="kg_bio_too_many_attempts_pattern" msgid="736884689355181602">"कई बार कोशिश की जा चुकी है, इसलिए पैटर्न ड्रा करें"</string>
diff --git a/packages/SystemUI/res-keyguard/values-my/strings.xml b/packages/SystemUI/res-keyguard/values-my/strings.xml
index f74eb66..c4fc5f7 100644
--- a/packages/SystemUI/res-keyguard/values-my/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-my/strings.xml
@@ -23,7 +23,7 @@
<string name="keyguard_enter_your_pin" msgid="5429932527814874032">"သင့်ပင်နံပါတ် ထည့်ပါ"</string>
<string name="keyguard_enter_pin" msgid="8114529922480276834">"ပင်နံပါတ်ထည့်ပါ"</string>
<string name="keyguard_enter_your_pattern" msgid="351503370332324745">"သင့်လော့ခ်ဖွင့်ပုံစံ ထည့်ပါ"</string>
- <string name="keyguard_enter_pattern" msgid="7616595160901084119">"ပုံစံဆွဲပါ"</string>
+ <string name="keyguard_enter_pattern" msgid="7616595160901084119">"ပုံဖော်ပါ"</string>
<string name="keyguard_enter_your_password" msgid="7225626204122735501">"သင့်စကားဝှက် ထည့်ပါ"</string>
<string name="keyguard_enter_password" msgid="6483623792371009758">"စကားဝှက် ထည့်ပါ"</string>
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"ကတ် မမှန်ကန်ပါ။"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ne/strings.xml b/packages/SystemUI/res-keyguard/values-ne/strings.xml
index 65440e8..2bfdef6 100644
--- a/packages/SystemUI/res-keyguard/values-ne/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ne/strings.xml
@@ -23,7 +23,7 @@
<string name="keyguard_enter_your_pin" msgid="5429932527814874032">"आफ्नो PIN हाल्नुहोस्"</string>
<string name="keyguard_enter_pin" msgid="8114529922480276834">"PIN हाल्नुहोस्"</string>
<string name="keyguard_enter_your_pattern" msgid="351503370332324745">"प्याटर्न हाल्नुहोस्"</string>
- <string name="keyguard_enter_pattern" msgid="7616595160901084119">"प्याटर्न कोर्नुहोस्"</string>
+ <string name="keyguard_enter_pattern" msgid="7616595160901084119">"प्याटर्न हाल्नुहोस्"</string>
<string name="keyguard_enter_your_password" msgid="7225626204122735501">"पासवर्ड हाल्नुहोस्"</string>
<string name="keyguard_enter_password" msgid="6483623792371009758">"पासवर्ड हाल्नुहोस्"</string>
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"अमान्य कार्ड।"</string>
@@ -57,11 +57,11 @@
<string name="kg_wrong_pin" msgid="4160978845968732624">"गलत PIN"</string>
<string name="kg_wrong_pin_try_again" msgid="3129729383303430190">"PIN मिलेन। फेरि प्रयास गर्नुहोस्।"</string>
<string name="kg_wrong_input_try_fp_suggestion" msgid="3143861542242024833">"वा फिंगरप्रिन्ट प्रयोग गरी अनलक गर्नुहोस्"</string>
- <string name="kg_fp_not_recognized" msgid="5183108260932029241">"फिंगरप्रिन्ट पहिचान गर्न सकिएन"</string>
+ <string name="kg_fp_not_recognized" msgid="5183108260932029241">"फिंगरप्रिन्ट मिलेन"</string>
<string name="bouncer_face_not_recognized" msgid="1666128054475597485">"अनुहार पहिचान गर्न सकिएन"</string>
<string name="kg_bio_try_again_or_pin" msgid="4752168242723808390">"फेरि प्रयास गर्नुहोस् वा PIN हाल्नुहोस्"</string>
<string name="kg_bio_try_again_or_password" msgid="1473132729225398039">"फेरि प्रयास गर्नुहोस् वा पासवर्ड हाल्नुहोस्"</string>
- <string name="kg_bio_try_again_or_pattern" msgid="4867893307468801501">"फेरि प्रयास गर्नुहोस् वा प्याटर्न कोर्नुहोस्"</string>
+ <string name="kg_bio_try_again_or_pattern" msgid="4867893307468801501">"फेरि प्रयास गर्नुहोस् वा प्याटर्न हाल्नुहोस्"</string>
<string name="kg_bio_too_many_attempts_pin" msgid="5850845723433047605">"अत्यन्तै धेरै पटक प्रयास गरिसकेपछि PIN हाल्नु पर्ने हुन्छ"</string>
<string name="kg_bio_too_many_attempts_password" msgid="5551690347827728042">"अत्यन्तै धेरै पटक प्रयास गरिसकेपछि पासवर्ड हाल्नु पर्ने हुन्छ"</string>
<string name="kg_bio_too_many_attempts_pattern" msgid="736884689355181602">"अत्यन्तै धेरै पटक प्रयास गरिसकेपछि प्याटर्न कोर्नु पर्ने हुन्छ"</string>
@@ -126,8 +126,8 @@
<string name="keyguard_unlock_to_continue" msgid="7509503484250597743">"आफ्नो डिभाइस अनलक गरी जारी राख्नुहोस्"</string>
<string name="kg_prompt_unattended_update_pin" msgid="5979434876768801873">"पछि अपडेट इन्स्टल गर्न PIN हाल्नुहोस्"</string>
<string name="kg_prompt_unattended_update_password" msgid="8805664437604967210">"पछि अपडेट इन्स्टल गर्न पासवर्ड हाल्नुहोस्"</string>
- <string name="kg_prompt_unattended_update_pattern" msgid="8580479377489546091">"पछि अपडेट इन्स्टल गर्न प्याटर्न कोर्नुहोस्"</string>
+ <string name="kg_prompt_unattended_update_pattern" msgid="8580479377489546091">"पछि अपडेट इन्स्टल गर्न प्याटर्न हाल्नुहोस्"</string>
<string name="kg_prompt_after_update_pin" msgid="7051709651908643013">"डिभाइस अपडेट गरिएको छ। जारी राख्न PIN हाल्नुहोस्।"</string>
<string name="kg_prompt_after_update_password" msgid="153703052501352094">"डिभाइस अपडेट गरिएको छ। जारी राख्न पासवर्ड हाल्नुहोस्।"</string>
- <string name="kg_prompt_after_update_pattern" msgid="1484084551298241992">"डिभाइस अपडेट गरिएको छ। जारी राख्न प्याटर्न कोर्नुहोस्।"</string>
+ <string name="kg_prompt_after_update_pattern" msgid="1484084551298241992">"डिभाइस अपडेट गरिएको छ। जारी राख्न प्याटर्न हाल्नुहोस्।"</string>
</resources>
diff --git a/packages/SystemUI/res-keyguard/values-nl/strings.xml b/packages/SystemUI/res-keyguard/values-nl/strings.xml
index 9fb9e1b..a35c3e6 100644
--- a/packages/SystemUI/res-keyguard/values-nl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-nl/strings.xml
@@ -25,7 +25,7 @@
<string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Voer je patroon in"</string>
<string name="keyguard_enter_pattern" msgid="7616595160901084119">"Teken het patroon"</string>
<string name="keyguard_enter_your_password" msgid="7225626204122735501">"Voer je wachtwoord in"</string>
- <string name="keyguard_enter_password" msgid="6483623792371009758">"Geef het wachtwoord op"</string>
+ <string name="keyguard_enter_password" msgid="6483623792371009758">"Voer het wachtwoord in"</string>
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Ongeldige kaart."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"Opgeladen"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Draadloos opladen"</string>
@@ -59,7 +59,7 @@
<string name="kg_wrong_input_try_fp_suggestion" msgid="3143861542242024833">"Of ontgrendel met vingerafdruk"</string>
<string name="kg_fp_not_recognized" msgid="5183108260932029241">"Vingerafdruk niet herkend"</string>
<string name="bouncer_face_not_recognized" msgid="1666128054475597485">"Gezicht niet herkend"</string>
- <string name="kg_bio_try_again_or_pin" msgid="4752168242723808390">"Probeer het opnieuw of geef de pincode op"</string>
+ <string name="kg_bio_try_again_or_pin" msgid="4752168242723808390">"Probeer het opnieuw of voer de pincode in"</string>
<string name="kg_bio_try_again_or_password" msgid="1473132729225398039">"Probeer het opnieuw of geef het wachtwoord op"</string>
<string name="kg_bio_try_again_or_pattern" msgid="4867893307468801501">"Probeer het opnieuw of teken het patroon"</string>
<string name="kg_bio_too_many_attempts_pin" msgid="5850845723433047605">"Na te veel pogingen is de pincode vereist"</string>
diff --git a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
index b292204..9a26f7d 100644
--- a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
@@ -57,7 +57,7 @@
<string name="kg_wrong_pin" msgid="4160978845968732624">"PIN incorreto"</string>
<string name="kg_wrong_pin_try_again" msgid="3129729383303430190">"PIN errado. Tente de novo."</string>
<string name="kg_wrong_input_try_fp_suggestion" msgid="3143861542242024833">"Ou desbloqueie com a impressão digital"</string>
- <string name="kg_fp_not_recognized" msgid="5183108260932029241">"Impr. dig. não reconhecida"</string>
+ <string name="kg_fp_not_recognized" msgid="5183108260932029241">"Impressão digital não reconhecida"</string>
<string name="bouncer_face_not_recognized" msgid="1666128054475597485">"Rosto não reconhecido"</string>
<string name="kg_bio_try_again_or_pin" msgid="4752168242723808390">"Tente novamente ou introduza o PIN"</string>
<string name="kg_bio_try_again_or_password" msgid="1473132729225398039">"Tente novamente ou introduza a palavra-passe"</string>
diff --git a/packages/SystemUI/res-keyguard/values-sr/strings.xml b/packages/SystemUI/res-keyguard/values-sr/strings.xml
index 34c9311..339a82a 100644
--- a/packages/SystemUI/res-keyguard/values-sr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sr/strings.xml
@@ -57,7 +57,7 @@
<string name="kg_wrong_pin" msgid="4160978845968732624">"Погрешан PIN"</string>
<string name="kg_wrong_pin_try_again" msgid="3129729383303430190">"Погрешан PIN. Пробајте поново."</string>
<string name="kg_wrong_input_try_fp_suggestion" msgid="3143861542242024833">"Или откључајте отиском прста"</string>
- <string name="kg_fp_not_recognized" msgid="5183108260932029241">"Отисак прста непрепознат"</string>
+ <string name="kg_fp_not_recognized" msgid="5183108260932029241">"Отисак прста није препознат"</string>
<string name="bouncer_face_not_recognized" msgid="1666128054475597485">"Лице није препознато"</string>
<string name="kg_bio_try_again_or_pin" msgid="4752168242723808390">"Пробајте поново или унесите PIN"</string>
<string name="kg_bio_try_again_or_password" msgid="1473132729225398039">"Пробајте поново или унесите лозинку"</string>
diff --git a/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml
index 7d74c9c..196df28 100644
--- a/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml
@@ -23,7 +23,7 @@
<string name="keyguard_enter_your_pin" msgid="5429932527814874032">"输入您的 PIN 码"</string>
<string name="keyguard_enter_pin" msgid="8114529922480276834">"输入 PIN 码"</string>
<string name="keyguard_enter_your_pattern" msgid="351503370332324745">"绘制解锁图案"</string>
- <string name="keyguard_enter_pattern" msgid="7616595160901084119">"绘制图案"</string>
+ <string name="keyguard_enter_pattern" msgid="7616595160901084119">"绘制解锁图案"</string>
<string name="keyguard_enter_your_password" msgid="7225626204122735501">"输入您的密码"</string>
<string name="keyguard_enter_password" msgid="6483623792371009758">"输入密码"</string>
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"SIM 卡无效。"</string>
@@ -61,7 +61,7 @@
<string name="bouncer_face_not_recognized" msgid="1666128054475597485">"无法识别面孔"</string>
<string name="kg_bio_try_again_or_pin" msgid="4752168242723808390">"请重试,或输入 PIN 码"</string>
<string name="kg_bio_try_again_or_password" msgid="1473132729225398039">"请重试,或输入密码"</string>
- <string name="kg_bio_try_again_or_pattern" msgid="4867893307468801501">"请重试,或绘制图案"</string>
+ <string name="kg_bio_try_again_or_pattern" msgid="4867893307468801501">"请重试,或绘制解锁图案"</string>
<string name="kg_bio_too_many_attempts_pin" msgid="5850845723433047605">"如果出错的尝试次数太多,必须输入 PIN 码才能解锁"</string>
<string name="kg_bio_too_many_attempts_password" msgid="5551690347827728042">"如果出错的尝试次数太多,必须输入密码才能解锁"</string>
<string name="kg_bio_too_many_attempts_pattern" msgid="736884689355181602">"如果出错的尝试次数太多,必须绘制图案才能解锁"</string>
diff --git a/packages/SystemUI/res-keyguard/values/styles.xml b/packages/SystemUI/res-keyguard/values/styles.xml
index c43e394..da12dd7 100644
--- a/packages/SystemUI/res-keyguard/values/styles.xml
+++ b/packages/SystemUI/res-keyguard/values/styles.xml
@@ -36,7 +36,6 @@
</style>
<style name="Keyguard.Bouncer.SecondaryMessage" parent="Theme.SystemUI">
<item name="android:textSize">14sp</item>
- <item name="android:lineHeight">20dp</item>
<item name="android:maxLines">@integer/bouncer_secondary_message_lines</item>
<item name="android:lines">@integer/bouncer_secondary_message_lines</item>
<item name="android:textAlignment">center</item>
diff --git a/packages/SystemUI/res/drawable/shelf_action_chip_divider.xml b/packages/SystemUI/res/drawable/shelf_action_chip_divider.xml
index a5b44e5..0a1f2a8 100644
--- a/packages/SystemUI/res/drawable/shelf_action_chip_divider.xml
+++ b/packages/SystemUI/res/drawable/shelf_action_chip_divider.xml
@@ -16,6 +16,6 @@
<shape xmlns:android = "http://schemas.android.com/apk/res/android">
<size
- android:width = "@dimen/overlay_action_chip_margin_start"
+ android:width = "@dimen/shelf_action_chip_margin_start"
android:height = "0dp"/>
</shape>
diff --git a/packages/SystemUI/res/layout/clipboard_overlay2.xml b/packages/SystemUI/res/layout/clipboard_overlay2.xml
new file mode 100644
index 0000000..33ad2cd
--- /dev/null
+++ b/packages/SystemUI/res/layout/clipboard_overlay2.xml
@@ -0,0 +1,191 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<com.android.systemui.clipboardoverlay.ClipboardOverlayView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/clipboard_ui"
+ android:theme="@style/FloatingOverlay"
+ android:alpha="0"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:contentDescription="@string/clipboard_overlay_window_name">
+ <FrameLayout
+ android:id="@+id/actions_container_background"
+ android:visibility="gone"
+ android:layout_height="0dp"
+ android:layout_width="0dp"
+ android:elevation="4dp"
+ android:background="@drawable/shelf_action_chip_container_background"
+ android:layout_marginStart="@dimen/overlay_action_container_margin_horizontal"
+ android:layout_marginBottom="@dimen/overlay_action_container_margin_bottom"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="@+id/actions_container"
+ app:layout_constraintEnd_toEndOf="@+id/actions_container"
+ app:layout_constraintBottom_toBottomOf="parent"/>
+ <HorizontalScrollView
+ android:id="@+id/actions_container"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="@dimen/overlay_action_container_margin_horizontal"
+ android:paddingEnd="@dimen/overlay_action_container_padding_end"
+ android:paddingVertical="@dimen/overlay_action_container_padding_vertical"
+ android:elevation="4dp"
+ android:scrollbars="none"
+ app:layout_constraintHorizontal_bias="0"
+ app:layout_constraintWidth_percent="1.0"
+ app:layout_constraintWidth_max="wrap"
+ app:layout_constraintStart_toEndOf="@+id/preview_border"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintBottom_toBottomOf="@id/actions_container_background">
+ <LinearLayout
+ android:id="@+id/actions"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingStart="@dimen/shelf_action_chip_margin_start"
+ android:showDividers="middle"
+ android:divider="@drawable/shelf_action_chip_divider"
+ android:animateLayoutChanges="true">
+ <include layout="@layout/shelf_action_chip"
+ android:id="@+id/share_chip"/>
+ <include layout="@layout/shelf_action_chip"
+ android:id="@+id/remote_copy_chip"/>
+ </LinearLayout>
+ </HorizontalScrollView>
+ <View
+ android:id="@+id/preview_border"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:layout_marginStart="@dimen/overlay_preview_container_margin"
+ android:layout_marginTop="@dimen/overlay_border_width_neg"
+ android:layout_marginEnd="@dimen/overlay_border_width_neg"
+ android:layout_marginBottom="@dimen/overlay_preview_container_margin"
+ android:elevation="7dp"
+ android:background="@drawable/overlay_border"
+ app:layout_constraintStart_toStartOf="@id/actions_container_background"
+ app:layout_constraintTop_toTopOf="@id/clipboard_preview"
+ app:layout_constraintEnd_toEndOf="@id/clipboard_preview"
+ app:layout_constraintBottom_toBottomOf="@id/actions_container_background"/>
+ <FrameLayout
+ android:id="@+id/clipboard_preview"
+ android:layout_width="@dimen/clipboard_preview_size"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="@dimen/overlay_border_width"
+ android:layout_marginBottom="@dimen/overlay_border_width"
+ android:layout_gravity="center"
+ android:elevation="7dp"
+ android:background="@drawable/overlay_preview_background"
+ android:clipChildren="true"
+ android:clipToOutline="true"
+ android:clipToPadding="true"
+ app:layout_constraintStart_toStartOf="@id/preview_border"
+ app:layout_constraintBottom_toBottomOf="@id/preview_border">
+ <TextView android:id="@+id/text_preview"
+ android:textFontWeight="500"
+ android:padding="8dp"
+ android:gravity="center|start"
+ android:ellipsize="end"
+ android:autoSizeTextType="uniform"
+ android:autoSizeMinTextSize="@dimen/clipboard_overlay_min_font"
+ android:autoSizeMaxTextSize="@dimen/clipboard_overlay_max_font"
+ android:textColor="?attr/overlayButtonTextColor"
+ android:textColorLink="?attr/overlayButtonTextColor"
+ android:background="?androidprv:attr/colorAccentSecondary"
+ android:layout_width="@dimen/clipboard_preview_size"
+ android:layout_height="@dimen/clipboard_preview_size"/>
+ <ImageView
+ android:id="@+id/image_preview"
+ android:scaleType="fitCenter"
+ android:adjustViewBounds="true"
+ android:contentDescription="@string/clipboard_image_preview"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"/>
+ <TextView
+ android:id="@+id/hidden_preview"
+ android:visibility="gone"
+ android:textFontWeight="500"
+ android:padding="8dp"
+ android:gravity="center"
+ android:textSize="14sp"
+ android:textColor="?attr/overlayButtonTextColor"
+ android:background="?androidprv:attr/colorAccentSecondary"
+ android:layout_width="@dimen/clipboard_preview_size"
+ android:layout_height="@dimen/clipboard_preview_size"/>
+ </FrameLayout>
+ <LinearLayout
+ android:id="@+id/minimized_preview"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:visibility="gone"
+ android:elevation="7dp"
+ android:padding="8dp"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ android:layout_marginStart="@dimen/overlay_action_container_margin_horizontal"
+ android:layout_marginBottom="@dimen/overlay_action_container_margin_bottom"
+ android:background="@drawable/clipboard_minimized_background">
+ <ImageView
+ android:src="@drawable/ic_content_paste"
+ android:tint="?attr/overlayButtonTextColor"
+ android:layout_width="24dp"
+ android:layout_height="24dp"/>
+ <ImageView
+ android:src="@*android:drawable/ic_chevron_end"
+ android:tint="?attr/overlayButtonTextColor"
+ android:layout_width="24dp"
+ android:layout_height="24dp"
+ android:paddingEnd="-8dp"
+ android:paddingStart="-4dp"/>
+ </LinearLayout>
+ <androidx.constraintlayout.widget.Barrier
+ android:id="@+id/clipboard_content_top"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ app:barrierDirection="top"
+ app:constraint_referenced_ids="clipboard_preview,minimized_preview"/>
+ <androidx.constraintlayout.widget.Barrier
+ android:id="@+id/clipboard_content_end"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ app:barrierDirection="end"
+ app:constraint_referenced_ids="clipboard_preview,minimized_preview"/>
+ <FrameLayout
+ android:id="@+id/dismiss_button"
+ android:layout_width="@dimen/overlay_dismiss_button_tappable_size"
+ android:layout_height="@dimen/overlay_dismiss_button_tappable_size"
+ android:elevation="10dp"
+ android:visibility="gone"
+ android:alpha="0"
+ app:layout_constraintStart_toEndOf="@id/clipboard_content_end"
+ app:layout_constraintEnd_toEndOf="@id/clipboard_content_end"
+ app:layout_constraintTop_toTopOf="@id/clipboard_content_top"
+ app:layout_constraintBottom_toTopOf="@id/clipboard_content_top"
+ android:contentDescription="@string/clipboard_dismiss_description">
+ <ImageView
+ android:id="@+id/dismiss_image"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_margin="@dimen/overlay_dismiss_button_margin"
+ android:background="@drawable/circular_background"
+ android:backgroundTint="?androidprv:attr/materialColorPrimaryFixedDim"
+ android:tint="?androidprv:attr/materialColorOnPrimaryFixed"
+ android:padding="4dp"
+ android:src="@drawable/ic_close"/>
+ </FrameLayout>
+</com.android.systemui.clipboardoverlay.ClipboardOverlayView>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/screenshot_shelf.xml b/packages/SystemUI/res/layout/screenshot_shelf.xml
index 7adfa6c..76f7f3b 100644
--- a/packages/SystemUI/res/layout/screenshot_shelf.xml
+++ b/packages/SystemUI/res/layout/screenshot_shelf.xml
@@ -23,7 +23,9 @@
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/screenshot_static"
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="match_parent"
+ android:clipChildren="false"
+ android:clipToPadding="false">
<FrameLayout
android:id="@+id/actions_container_background"
android:visibility="gone"
@@ -84,6 +86,22 @@
android:clickable="true"
app:layout_constraintStart_toStartOf="@id/screenshot_preview_border"
app:layout_constraintBottom_toBottomOf="@id/screenshot_preview_border"/>
+ <!-- Keep the same dimension with screenshot_preview. -->
+ <ImageView
+ android:id="@+id/screenshot_preview_blur"
+ android:layout_width="@dimen/overlay_x_scale"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="@dimen/overlay_border_width"
+ android:layout_marginBottom="@dimen/overlay_border_width"
+ android:layout_gravity="center"
+ android:elevation="4dp"
+ android:contentDescription="@string/screenshot_edit_description"
+ android:scaleType="fitEnd"
+ android:background="@drawable/overlay_preview_background"
+ android:adjustViewBounds="true"
+ android:visibility="invisible"
+ app:layout_constraintStart_toStartOf="@id/screenshot_preview_border"
+ app:layout_constraintBottom_toBottomOf="@id/screenshot_preview_border"/>
<ImageView
android:id="@+id/screenshot_badge"
android:layout_width="56dp"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 3861c98..ac523c1 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Linkergrens <xliff:g id="PERCENT">%1$d</xliff:g> persent"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Regtergrens <xliff:g id="PERCENT">%1$d</xliff:g> persent"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Gestoor in <xliff:g id="APP">%1$s</xliff:g> in die werkprofiel"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Gestoor in <xliff:g id="APP">%1$s</xliff:g> in die privaat profiel"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Lêers"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> het hierdie skermskoot bespeur."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> en ander oop apps het hierdie skermskoot bespeur."</string>
@@ -459,6 +460,11 @@
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Maak legstukke op sluitskerm toe"</string>
<string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Pasmaak legstukke"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Legstukke op sluitskerm"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"kies legstuk"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Wissel gebruiker"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"aftrekkieslys"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alle programme en data in hierdie sessie sal uitgevee word."</string>
@@ -627,6 +633,7 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"ontdemp %s"</string>
<string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> speel tans op"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"Oudio sal speel op"</string>
+ <string name="media_output_title_ongoing_call" msgid="208426888064112006">"Bel met"</string>
<string name="system_ui_tuner" msgid="1471348823289954729">"Stelsel-UI-ontvanger"</string>
<string name="status_bar" msgid="4357390266055077437">"Statusbalk"</string>
<string name="demo_mode" msgid="263484519766901593">"Stelsel-UI-demonstrasiemodus"</string>
@@ -654,10 +661,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satelliet, swak verbinding"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelliet, goeie toestand"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelliet, verbinding is beskikbaar"</string>
- <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
- <skip />
- <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
- <skip />
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satelliet-SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Werkprofiel"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Pret vir party mense, maar nie vir almal nie"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Stelsel-UI-ontvanger gee jou ekstra maniere om die Android-gebruikerkoppelvlak in te stel en te pasmaak. Hierdie eksperimentele kenmerke kan in toekomstige uitreikings verander, breek of verdwyn. Gaan versigtig voort."</string>
@@ -862,6 +866,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Voeg teël by"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Skuif na <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Voeg by posisie <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Posisie is ongeldig."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Posisie <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Teël is bygevoeg"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Teël is verwyder"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 9f9d3c5..1236c97 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"የግራ ወሰን <xliff:g id="PERCENT">%1$d</xliff:g> በመቶ"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"የቀኝ ወሰን <xliff:g id="PERCENT">%1$d</xliff:g> በመቶ"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"<xliff:g id="APP">%1$s</xliff:g> ውስጥ የስራ መገለጫው ውስጥ ተቀምጧል"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"በግል መገለጫው ውስጥ በ<xliff:g id="APP">%1$s</xliff:g> ውስጥ ተቀምጧል"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"ፋይሎች"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> ይህን ቅጽበታዊ ገፅ ዕይታ ለይቷል።"</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> እና ሌሎች ክፍት መተግበሪያዎች ይህን ቅጽበታዊ ገፅ ዕይታ ለይተዋል።"</string>
@@ -457,9 +458,13 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"የሥራ መተግበሪያዎች ከቆሙበት ይቀጥሉ?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"ከቆመበት ቀጥል"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"ምግብሮችን በማያ ገጽ ቁልፍ ላይ ዝጋ"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"ምግብሮችን አብጅ"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"ምግብሮች በማያ ገጽ ቁልፍ ላይ"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"ምግብር ይምረጡ"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ተጠቃሚ ቀይር"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ወደታች ተጎታች ምናሌ"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"በዚህ ክፍለ-ጊዜ ውስጥ ያሉ ሁሉም መተግበሪያዎች እና ውሂብ ይሰረዛሉ።"</string>
@@ -628,6 +633,7 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"የ%s ድምፀ-ከል አንሳ"</string>
<string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> እየተጫወተ ያለው በ"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"ኦዲዮ ይጫወታል በ"</string>
+ <string name="media_output_title_ongoing_call" msgid="208426888064112006">"በጥሪ ላይ"</string>
<string name="system_ui_tuner" msgid="1471348823289954729">"የስርዓት በይነገጽ መቃኛ"</string>
<string name="status_bar" msgid="4357390266055077437">"የሁኔታ አሞሌ"</string>
<string name="demo_mode" msgid="263484519766901593">"የስርዓት ተጠቃሚ በይነገጽ ማሳያ ሁነታ"</string>
@@ -655,8 +661,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"ሳተላይት፣ ደካማ ግንኙነት"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"ሳተላይት፣ ጥሩ ግንኙነት"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ሳተላይት፣ ግንኙነት አለ"</string>
- <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"ከሳተላይት ጋር ተገናኝቷል"</string>
- <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"ከሳተላይት ጋር አልተገናኘም"</string>
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"ሳተላይት ኤስኦኤስ"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"የስራ መገለጫ"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"ለአንዳንዶች አስደሳች ቢሆንም ለሁሉም አይደለም"</string>
<string name="tuner_warning" msgid="1861736288458481650">"የስርዓት በይነገጽ መቃኛ የAndroid ተጠቃሚ በይነገጹን የሚነካኩበት እና የሚያበጁበት ተጨማሪ መንገዶች ይሰጠዎታል። እነዚህ የሙከራ ባህሪዎች ወደፊት በሚኖሩ ልቀቶች ላይ ሊለወጡ፣ ሊሰበሩ ወይም ሊጠፉ ይችላሉ። ከጥንቃቄ ጋር ወደፊት ይቀጥሉ።"</string>
@@ -861,6 +866,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"ሰቅ ያክሉ"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"ወደ <xliff:g id="POSITION">%1$d</xliff:g> ውሰድ"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"ወደ <xliff:g id="POSITION">%1$d</xliff:g> ቦታ አክል"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"አቀማመጡ ተቀባይነት የለውም።"</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"የ<xliff:g id="POSITION">%1$d</xliff:g> አቀማመጥ"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"ሰቅ ታክሏል"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"ሰቅ ተወግዷል"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 1897228..2eed2aa 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"الحد الأيسر <xliff:g id="PERCENT">%1$d</xliff:g> في المئة"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"الحد الأيمن <xliff:g id="PERCENT">%1$d</xliff:g> في المئة"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"تم حفظ لقطة الشاشة في \"<xliff:g id="APP">%1$s</xliff:g>\" في ملف العمل."</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"تم حفظ لقطة الشاشة في \"<xliff:g id="APP">%1$s</xliff:g>\" في الملف الشخصي الخاص."</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"الملفات"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"رصَد تطبيق \"<xliff:g id="APPNAME">%1$s</xliff:g>\" لقطة الشاشة هذه."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"رصَد تطبيق \"<xliff:g id="APPNAME">%1$s</xliff:g>\" والتطبيقات المفتوحة الأخرى لقطة الشاشة هذه."</string>
@@ -459,6 +460,11 @@
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"إغلاق التطبيقات المصغّرة على شاشة القفل"</string>
<string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"تخصيص التطبيقات المصغَّرة"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"التطبيقات المصغّرة على شاشة القفل"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"اختيار التطبيق المصغّر"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"تبديل المستخدم"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"القائمة المنسدلة"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"سيتم حذف كل التطبيقات والبيانات في هذه الجلسة."</string>
@@ -627,6 +633,8 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"إعادة صوت \"%s\""</string>
<string name="media_output_label_title" msgid="872824698593182505">"تشغيل <xliff:g id="LABEL">%s</xliff:g> على"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"سيتم تشغيل الصوت على"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"أداة ضبط واجهة مستخدم النظام"</string>
<string name="status_bar" msgid="4357390266055077437">"شريط الحالة"</string>
<string name="demo_mode" msgid="263484519766901593">"وضع تجريبي لواجهة مستخدم النظام"</string>
@@ -654,8 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"قمر صناعي، الاتصال ضعيف"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"قمر صناعي، الاتصال جيد"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"قمر صناعي، الاتصال متوفّر"</string>
- <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"تم الاتصال بالقمر الصناعي"</string>
- <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"لم يتم الاتصال بالقمر الصناعي"</string>
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"اتصالات الطوارئ بالقمر الصناعي"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"ملف العمل"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"متعة للبعض وليس للجميع"</string>
<string name="tuner_warning" msgid="1861736288458481650">"توفر لك أداة ضبط واجهة مستخدم النظام طرقًا إضافية لتعديل واجهة مستخدم Android وتخصيصها. ويمكن أن تطرأ تغييرات على هذه الميزات التجريبية أو يمكن أن تتعطل هذه الميزات أو تختفي في الإصدارات المستقبلية. عليك متابعة الاستخدام مع توخي الحذر."</string>
@@ -860,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"إضافة بطاقة"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"الانتقال إلى <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"الإضافة إلى الموضع <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"الموضِع غير صالح."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"الموضع: <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"تمت إضافة البطاقة."</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"تمت إزالة البطاقة."</string>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index ab19d56..16cd64b 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"বাওঁফালৰ সীমা <xliff:g id="PERCENT">%1$d</xliff:g> শতাংশ"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"সোঁফালৰ সীমা <xliff:g id="PERCENT">%1$d</xliff:g> শতাংশ"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"<xliff:g id="APP">%1$s</xliff:g> কৰ্মস্থানৰ প্ৰ’ফাইলত ছেভ কৰা হৈছে"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"ব্যক্তিগত প্ৰ’ফাইলত <xliff:g id="APP">%1$s</xliff:g>ত ছেভ কৰা হৈছে"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"ফাইল"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g>এ এই স্ক্ৰীনশ্বটটো চিনাক্ত কৰিছে।"</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> আৰু আন খোলা এপ্সমূহে এই স্ক্ৰীনশ্বটটো চিনাক্ত কৰিছে।"</string>
@@ -457,9 +458,13 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"কাম সম্পৰ্কীয় এপ্ আনপজ কৰিবনে?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"আনপজ কৰক"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"লক স্ক্ৰীনত ৱিজেট বন্ধ কৰক"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"ৱিজেট কাষ্টমাইজ কৰক"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"লক স্ক্ৰীনত ৱিজেট"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"ৱিজেট বাছনি কৰক"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ব্যৱহাৰকাৰী সলনি কৰক"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"পুল-ডাউনৰ মেনু"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"এই ছেশ্বনৰ আটাইবোৰ এপ্ আৰু ডেটা মচা হ\'ব।"</string>
@@ -628,6 +633,7 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"%s আনমিউট কৰক"</string>
<string name="media_output_label_title" msgid="872824698593182505">"ইয়াত <xliff:g id="LABEL">%s</xliff:g> প্লে’ হৈ আছে"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"অডিঅ’ ইয়াত প্লে’ হ’ব"</string>
+ <string name="media_output_title_ongoing_call" msgid="208426888064112006">"কল চলি আছে"</string>
<string name="system_ui_tuner" msgid="1471348823289954729">"System UI Tuner"</string>
<string name="status_bar" msgid="4357390266055077437">"স্থিতি দণ্ড"</string>
<string name="demo_mode" msgid="263484519766901593">"ছিষ্টেমৰ UI প্ৰদৰ্শন ম\'ড"</string>
@@ -655,8 +661,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"উপগ্ৰহ, বেয়া সংযোগ"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"উপগ্ৰহ, ভাল সংযোগ"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"উপগ্ৰহ, সংযোগ উপলব্ধ"</string>
- <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"উপগ্ৰহৰ সৈতে সংযোগ কৰা হৈছে"</string>
- <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"উপগ্ৰহৰ সৈতে সংযোগ কৰা হোৱা নাই"</string>
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"উপগ্ৰহ SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"কৰ্মস্থানৰ প্ৰ\'ফাইল"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"কিছুমানৰ বাবে আমোদজনক হয় কিন্তু সকলোৰে বাবে নহয়"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tunerএ আপোনাক Android ব্যৱহাৰকাৰী ইণ্টাৰফেইচ সলনি কৰিবলৈ আৰু নিজৰ উপযোগিতা অনুসৰি ব্যৱহাৰ কৰিবলৈ অতিৰিক্ত সুবিধা প্ৰদান কৰে। এই পৰীক্ষামূলক সুবিধাসমূহ সলনি হ\'ব পাৰে, সেইবোৰে কাম নকৰিব পাৰে বা আগন্তুক সংস্কৰণসমূহত সেইবোৰ অন্তৰ্ভুক্ত কৰা নহ’ব পাৰে। সাৱধানেৰে আগবাঢ়ক।"</string>
@@ -861,6 +866,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"টাইল যোগ দিয়ক"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g> নম্বৰলৈ স্থানান্তৰ কৰক"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g> নম্বৰ স্থানত যোগ দিয়ক"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"স্থান অমান্য।"</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"<xliff:g id="POSITION">%1$d</xliff:g> নম্বৰ স্থান"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"টাইল যোগ দিয়া হৈছে"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"টাইল আঁতৰোৱা হৈছে"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 62164a5..69cec1c 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Sol sərhəd <xliff:g id="PERCENT">%1$d</xliff:g> faiz"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Sağ sərhəd <xliff:g id="PERCENT">%1$d</xliff:g> faiz"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"İş profilində <xliff:g id="APP">%1$s</xliff:g> tətbiqində saxlanıb"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Şəxsi profildə <xliff:g id="APP">%1$s</xliff:g> tətbiqində yadda saxlanılıb"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Fayllar"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> bu skrinşotu aşkarladı."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> və digər açıq tətbiqlər bu skrinşotu aşkarladı."</string>
@@ -459,6 +460,11 @@
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Kilid ekranında vidcetləri bağlayın"</string>
<string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Vidcetləri fərdiləşdirin"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Kilid ekranındakı vidcetlər"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"vidcet seçin"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Switch user"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"aşağı çəkilən menyu"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Bu sessiyada bütün tətbiqlər və data silinəcək."</string>
@@ -627,6 +633,7 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"%s seçimini səssiz rejimdən çıxarın"</string>
<string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> tətbiqində oxudulur"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"Audio oxudulacaq"</string>
+ <string name="media_output_title_ongoing_call" msgid="208426888064112006">"Zəng edilir"</string>
<string name="system_ui_tuner" msgid="1471348823289954729">"System UI Tuner"</string>
<string name="status_bar" msgid="4357390266055077437">"Status paneli"</string>
<string name="demo_mode" msgid="263484519766901593">"Sistem interfeysi: demorejim"</string>
@@ -654,10 +661,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Peyk, bağlantı zəifdir"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Peyk, bağlantı yaxşıdır"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Peyk, bağlantı var"</string>
- <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
- <skip />
- <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
- <skip />
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Təcili peyk bağlantısı"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"İş profili"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Hamı üçün deyil, bəziləri üçün əyləncəli"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner Android istifadəçi interfeysini dəyişdirmək və fərdiləşdirmək üçün Sizə ekstra yollar təklif edir."</string>
@@ -862,6 +866,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Lövhə əlavə edin"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g> mövqeyinə köçürün"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g> mövqeyinə əlavə edin"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Mövqe yanlışdır."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"<xliff:g id="POSITION">%1$d</xliff:g> mövqeyi"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Mozaik əlavə edilib"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Mozaik silinib"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 392ca53..c2cc34a 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Leva ivica <xliff:g id="PERCENT">%1$d</xliff:g> posto"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Desna ivica <xliff:g id="PERCENT">%1$d</xliff:g> posto"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Sačuvano je u aplikaciji <xliff:g id="APP">%1$s</xliff:g> na poslovnom profilu"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Sačuvano je u aplikaciji <xliff:g id="APP">%1$s</xliff:g> na privatnom profilu"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Fajlovi"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"Aplikacija <xliff:g id="APPNAME">%1$s</xliff:g> je otkrila ovaj snimak ekrana."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> i druge otvorene aplikacije su otkrile ovaj snimak ekrana."</string>
@@ -457,9 +458,13 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Uključiti poslovne aplikacije?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Ponovo aktiviraj"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Zatvorite vidžete na zaključanom ekranu"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Prilagodite vidžete"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Vidžeti na zaključanom ekranu"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"izaberite vidžet"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Zameni korisnika"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"padajući meni"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Sve aplikacije i podaci u ovoj sesiji će biti izbrisani."</string>
@@ -628,6 +633,8 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"uključite zvuk za: %s"</string>
<string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> se pušta na"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"Zvuk se pušta na"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"Tjuner za korisnički interfejs sistema"</string>
<string name="status_bar" msgid="4357390266055077437">"Statusna traka"</string>
<string name="demo_mode" msgid="263484519766901593">"Režim demonstracije za korisnički interfejs sistema"</string>
@@ -655,8 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satelit, veza je loša"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelit, veza je dobra"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, veza je dostupna"</string>
- <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"Povezano sa satelitom"</string>
- <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"Nije povezano sa satelitom"</string>
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Hitna pomoć preko satelita"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Poslovni profil"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Zabava za neke, ali ne za sve"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Tjuner za korisnički interfejs sistema vam pruža dodatne načine za podešavanje i prilagođavanje Android korisničkog interfejsa. Ove eksperimentalne funkcije mogu da se promene, otkažu ili nestanu u budućim izdanjima. Budite oprezni."</string>
@@ -861,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Dodajte pločicu"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Premestite na <xliff:g id="POSITION">%1$d</xliff:g>. poziciju"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Dodajte na <xliff:g id="POSITION">%1$d</xliff:g>. poziciju"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Pozicija je nevažeća."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"<xliff:g id="POSITION">%1$d</xliff:g>. pozicija"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Pločica je dodata"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Pločica je uklonjena"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 9977857..f956c0f 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -97,6 +97,8 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Левая граніца: <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Правая граніца: <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Захавана ў праграму \"<xliff:g id="APP">%1$s</xliff:g>\" (у працоўным профілі)"</string>
+ <!-- no translation found for screenshot_private_profile_notification (1704440899154243171) -->
+ <skip />
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Файлы"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"Праграма \"<xliff:g id="APPNAME">%1$s</xliff:g>\" выявіла гэты здымак экрана."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> і іншыя адкрытыя праграмы выявілі гэты здымак экрана."</string>
@@ -457,9 +459,14 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Уключыць працоўныя праграмы?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Уключыць"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Закрыць віджэты на экране блакіроўкі"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Наладзіць віджэты"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Віджэты на экране блакіроўкі"</string>
+ <!-- no translation found for accessibility_action_label_select_widget (8897281501387398191) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Перайсці да іншага карыстальніка"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"высоўнае меню"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Усе праграмы і даныя гэтага сеанса будуць выдалены."</string>
@@ -628,6 +635,7 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"уключыць гук (%s)"</string>
<string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> прайграецца тут:"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"Аўдыявыхад:"</string>
+ <string name="media_output_title_ongoing_call" msgid="208426888064112006">"Ідзе выклік"</string>
<string name="system_ui_tuner" msgid="1471348823289954729">"Наладка сістэмнага інтэрфейсу карыстальніка"</string>
<string name="status_bar" msgid="4357390266055077437">"Панэль стану"</string>
<string name="demo_mode" msgid="263484519766901593">"Рэжым дэманстрацыі сістэмнага інтэрфейсу карыстальніка"</string>
@@ -655,9 +663,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Спадарожнікавая сувязь, дрэннае падключэнне"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Спадарожнікавая сувязь, добрае падключэнне"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Спадарожнікавая сувязь, падключэнне даступнае"</string>
- <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
- <skip />
- <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+ <!-- no translation found for satellite_connected_carrier_text (118524195198532589) -->
<skip />
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Працоўны профіль"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Цікава для некаторых, але не для ўсіх"</string>
@@ -863,6 +869,8 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Дадаць плітку"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Перамясціць на пазіцыю <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Дадаць на пазіцыю <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <!-- no translation found for accessibilit_qs_edit_tile_add_move_invalid_position (2858467994472624487) -->
+ <skip />
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Пазіцыя <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Плітка дададзена"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Плітка выдалена"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 5b97cb4..c9d0cd2 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Лява граница: <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Дясна граница: <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Запазена в(ъв) <xliff:g id="APP">%1$s</xliff:g> в служебния потребителски профил"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Запазена в(ъв) <xliff:g id="APP">%1$s</xliff:g> в личния потребителски профил"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Files"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> установи заснемането на тази екранна снимка."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> и други отворени приложения установиха заснемането на тази екранна снимка."</string>
@@ -459,6 +460,11 @@
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Затваряне на приспособленията на заключения екран"</string>
<string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Персонализиране на приспособленията"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Приспособления на заключения екран"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"избиране на приспособление"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Превключване между потребителите"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"падащо меню"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Всички приложения и данни в тази сесия ще бъдат изтрити."</string>
@@ -627,6 +633,7 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"включване на звука на %s"</string>
<string name="media_output_label_title" msgid="872824698593182505">"Възпроизвеждане на <xliff:g id="LABEL">%s</xliff:g> на"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"Аудиото ще се възпроизвежда на"</string>
+ <string name="media_output_title_ongoing_call" msgid="208426888064112006">"Активно обаждане"</string>
<string name="system_ui_tuner" msgid="1471348823289954729">"Тунер на системния потребителски интерфейс"</string>
<string name="status_bar" msgid="4357390266055077437">"Лента на състоянието"</string>
<string name="demo_mode" msgid="263484519766901593">"Демонстрационен режим на системния ПИ"</string>
@@ -654,8 +661,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Сателит, лоша връзка"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Сателит, добра връзка"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Сателит, налице е връзка"</string>
- <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"Установена е връзка със сателит"</string>
- <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"Не е установена връзка със сателит"</string>
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS чрез сателит"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Потребителски профил в Work"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Забавно – но не за всички"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Тунерът на системния потребителски интерфейс ви предоставя допълнителни възможности за прецизиране и персонализиране на практическата работа с Android. Тези експериментални функции може да се променят, повредят или да изчезнат в бъдещите версии. Действайте внимателно."</string>
@@ -860,6 +866,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Добавяне на панел"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Преместване към позиция <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Добавяне към позиция <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Невалидна позиция."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Позиция <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Панелът е добавен"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Панелът е премахнат"</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 322b723..e2b4a6d 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"বাঁ প্রান্ত থেকে <xliff:g id="PERCENT">%1$d</xliff:g> শতাংশ"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"ডান প্রান্ত থেকে <xliff:g id="PERCENT">%1$d</xliff:g> percent"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"অফিস প্রোফাইলের মধ্যে <xliff:g id="APP">%1$s</xliff:g>-এ সেভ করা হয়েছে"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"<xliff:g id="APP">%1$s</xliff:g>-এ ব্যক্তিগত প্রোফাইলে সেভ করা হয়েছে"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"ফাইল"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g>, এই স্ক্রিনশট শনাক্ত করেছে।"</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> এবং খোলা থাকা অন্য অ্যাপ এই স্ক্রিনশট শনাক্ত করেছে।"</string>
@@ -457,9 +458,13 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"অফিসের অ্যাপ আনপজ করতে চান?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"আনপজ করুন"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"লক স্ক্রিনে উইজেট বন্ধ করুন"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"উইজেট কাস্টমাইজ করুন"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"লক স্ক্রিনে উইজেট"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"উইজেট বেছে নিন"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ব্যবহারকারী পাল্টে দিন"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"পুলডাউন মেনু"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"এই সেশনের সব অ্যাপ ও ডেটা মুছে ফেলা হবে।"</string>
@@ -627,7 +632,9 @@
<string name="volume_panel_hint_mute" msgid="6962563028495243738">"%s মিউট করুন"</string>
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"%s আনমিউট করুন"</string>
<string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g>-এ প্লে করা হচ্ছে"</string>
- <string name="media_output_title_without_playing" msgid="3825663683169305013">"অডিও প্লে করা হবে"</string>
+ <string name="media_output_title_without_playing" msgid="3825663683169305013">"অডিও এতে প্লে করা হবে"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"সিস্টেম UI টিউনার"</string>
<string name="status_bar" msgid="4357390266055077437">"স্ট্যাটাস বার"</string>
<string name="demo_mode" msgid="263484519766901593">"সিস্টেম UI ডেমো মোড"</string>
@@ -655,10 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"স্যাটেলাইট, খারাপ কানেকশন"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"স্যাটেলাইট, ভালো কানেকশন"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"স্যাটেলাইট, কানেকশন উপলভ্য আছে"</string>
- <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
- <skip />
- <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
- <skip />
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"স্যাটেলাইট SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"কাজের প্রোফাইল"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"কিছু ব্যক্তির জন্য মজাদার কিন্তু সকলের জন্য নয়"</string>
<string name="tuner_warning" msgid="1861736288458481650">"এই পরীক্ষামূলক বৈশিষ্ট্যগুলি ভবিষ্যতের সংস্করণগুলির মধ্যে পরিবর্তিত, বিভাজিত এবং অদৃশ্য হয়ে যেতে পারে৷ সাবধানতার সাথে এগিয়ে যান৷ সিস্টেম UI টিউনার আপনাকে Android ব্যবহারকারী ইন্টারফেসের সূক্ষ্ম সমন্বয় এবং কাস্টমাইজ করার অতিরিক্ত উপায়গুলি প্রদান করে৷"</string>
@@ -863,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"টাইল যোগ করুন"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g>-এ সরান"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"অবস্থান <xliff:g id="POSITION">%1$d</xliff:g>-এ যোগ করুন"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"পজিশন সঠিক নয়।"</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"অবস্থান <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"টাইল যোগ করা হয়েছে"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"টাইল সরানো হয়েছে"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 63340d7..108bed8 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Lijeva granica <xliff:g id="PERCENT">%1$d</xliff:g> posto"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Desna granica <xliff:g id="PERCENT">%1$d</xliff:g> posto"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Sačuvano je u aplikaciji <xliff:g id="APP">%1$s</xliff:g> na radnom profilu"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Sačuvano je u aplikaciji <xliff:g id="APP">%1$s</xliff:g> na privatnom profilu"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Fajlovi"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"Aplikacija <xliff:g id="APPNAME">%1$s</xliff:g> je otkrila ovaj snimak ekrana."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"Aplikacija <xliff:g id="APPNAME">%1$s</xliff:g> i druge otvorene aplikacije su otkrile ovaj snimak ekrana."</string>
@@ -457,9 +458,13 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Pokrenuti poslovne aplikacije?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Ponovo pokreni"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Zatvaranje vidžeta na zaključanom ekranu"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Prilagođavanje vidžeta"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Vidžeti na zaključanom ekranu"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"odabir vidžeta"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Zamijeni korisnika"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"padajući meni"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Sve aplikacije i podaci iz ove sesije će se izbrisati."</string>
@@ -626,8 +631,10 @@
<string name="volume_panel_collapsed_sliders" msgid="1413383759434791450">"Klizači jačine zvuka su suženi"</string>
<string name="volume_panel_hint_mute" msgid="6962563028495243738">"isključivanje parametra %s"</string>
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"uključivanje parametra %s"</string>
- <string name="media_output_label_title" msgid="872824698593182505">"Reproduciranje: <xliff:g id="LABEL">%s</xliff:g>"</string>
+ <string name="media_output_label_title" msgid="872824698593182505">"Reproducira se <xliff:g id="LABEL">%s</xliff:g> na"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"Reprodukcija zvuka na"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"Podešavač za korisnički interfejs sistema"</string>
<string name="status_bar" msgid="4357390266055077437">"Statusna traka"</string>
<string name="demo_mode" msgid="263484519766901593">"Demo način rada Sistemskog UI-ja"</string>
@@ -655,10 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satelit, slaba veza"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelit, dobra veza"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, veza je dostupna"</string>
- <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
- <skip />
- <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
- <skip />
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Hitna pomoć putem satelita"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Radni profil"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Zabava za neke, ali ne za sve"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Podešavač za korisnički interfejs sistema vam omogućava dodatne načine da podesite i prilagodite Androidov interfejs. Ove eksperimentalne funkcije se u budućim verzijama mogu mijenjati, kvariti ili nestati. Budite oprezni."</string>
@@ -863,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Dodavanje kartice"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Pomjeranje u položaj <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Dodavanje u položaj <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Nevažeći položaj."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Položaj <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Kartica je dodana"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Kartica je uklonjena"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 341dca5..48fadbc 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Marge esquerre <xliff:g id="PERCENT">%1$d</xliff:g> per cent"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Marge dret <xliff:g id="PERCENT">%1$d</xliff:g> per cent"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"S\'ha desat al perfil de treball de <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"S\'ha desat a <xliff:g id="APP">%1$s</xliff:g> al perfil privat"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Fitxers"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> ha detectat aquesta captura de pantalla."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> i altres aplicacions obertes han detectat aquesta captura de pantalla."</string>
@@ -457,9 +458,13 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Reactivar les apps de treball?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Reactiva"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Tanca els widgets a la pantalla de bloqueig"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Personalitza els widgets"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widgets a la pantalla de bloqueig"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"selecciona el widget"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Canvia d\'usuari"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menú desplegable"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Totes les aplicacions i les dades d\'aquesta sessió se suprimiran."</string>
@@ -628,6 +633,8 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"deixa de silenciar %s"</string>
<string name="media_output_label_title" msgid="872824698593182505">"S\'està reproduint <xliff:g id="LABEL">%s</xliff:g> a"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"Es reproduirà a"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"Personalitzador d\'interfície d\'usuari"</string>
<string name="status_bar" msgid="4357390266055077437">"Barra d\'estat"</string>
<string name="demo_mode" msgid="263484519766901593">"Mode de demostració de la IU del sistema"</string>
@@ -655,10 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satèl·lit, connexió deficient"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satèl·lit, bona connexió"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satèl·lit, connexió disponible"</string>
- <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
- <skip />
- <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
- <skip />
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS per satèl·lit"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Perfil de treball"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Diversió per a uns quants, però no per a tothom"</string>
<string name="tuner_warning" msgid="1861736288458481650">"El Personalitzador d\'interfície d\'usuari presenta opcions addicionals per canviar i personalitzar la interfície d\'usuari d\'Android. És possible que aquestes funcions experimentals canviïn, deixin de funcionar o desapareguin en versions futures. Continua amb precaució."</string>
@@ -863,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Afegeix una icona"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Mou a la posició <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Afegeix a la posició <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"La posició no és vàlida."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Posició <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"El mosaic s\'ha afegit"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"El mosaic s\'ha suprimit"</string>
@@ -1195,7 +1200,7 @@
<string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Per ara la Wi‑Fi no es connectarà automàticament"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Mostra-ho tot"</string>
<string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Per canviar de xarxa, desconnecta la connexió Ethernet"</string>
- <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Per millorar l\'experiència del dispositiu, les aplicacions i els serveis poden cercar xarxes Wi‑Fi en qualsevol moment, fins i tot quan la Wi‑Fi estigui desactivada. Pots canviar aquesta opció a la configuració de cerca de xarxes Wi‑Fi. "<annotation id="link">"Canvia-la"</annotation>"."</string>
+ <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Per millorar l\'experiència amb el dispositiu, les aplicacions i els serveis poden continuar cercant xarxes Wi‑Fi en qualsevol moment, fins i tot amb la Wi‑Fi desactivada. Pots canviar aquesta opció a la configuració de cerca de xarxes Wi‑Fi. "<annotation id="link">"Canvia-la"</annotation>"."</string>
<string name="turn_off_airplane_mode" msgid="8425587763226548579">"Desactiva el mode d\'avió"</string>
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> vol afegir la icona següent a la configuració ràpida"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Afegeix la icona"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 0598097..c90a023 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Levý okraj <xliff:g id="PERCENT">%1$d</xliff:g> procent"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Pravý okraj <xliff:g id="PERCENT">%1$d</xliff:g> procent"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Uloženo v aplikaci <xliff:g id="APP">%1$s</xliff:g> v pracovním profilu"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Uloženo do aplikace <xliff:g id="APP">%1$s</xliff:g> v soukromém profilu"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Soubory"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"Aplikace <xliff:g id="APPNAME">%1$s</xliff:g> objevila tento snímek obrazovky."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> a ostatní otevřené aplikace objevily tento snímek obrazovky."</string>
@@ -457,9 +458,13 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Zrušit pozastavení pracovních aplikací?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Zrušit pozastavení"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Zavřít widgety na obrazovce uzamčení"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Přizpůsobit widgety"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widgety na obrazovce uzamčení"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"vybrat widget"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Přepnout uživatele"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"rozbalovací nabídka"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Veškeré aplikace a data v této relaci budou vymazána."</string>
@@ -626,8 +631,10 @@
<string name="volume_panel_collapsed_sliders" msgid="1413383759434791450">"Posuvníky hlasitosti jsou sbalené"</string>
<string name="volume_panel_hint_mute" msgid="6962563028495243738">"ztlumíte %s"</string>
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"zapnete zvuk %s"</string>
- <string name="media_output_label_title" msgid="872824698593182505">"Přehrávání <xliff:g id="LABEL">%s</xliff:g> na"</string>
- <string name="media_output_title_without_playing" msgid="3825663683169305013">"Zvuk se přehraje přes"</string>
+ <string name="media_output_label_title" msgid="872824698593182505">"Přehrávání <xliff:g id="LABEL">%s</xliff:g> přes"</string>
+ <string name="media_output_title_without_playing" msgid="3825663683169305013">"Zvuk se bude přehrávat přes"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"Nástroj na ladění uživatelského rozhraní systému"</string>
<string name="status_bar" msgid="4357390266055077437">"Stavový řádek"</string>
<string name="demo_mode" msgid="263484519766901593">"Ukázkový režim uživatelského rozhraní systému"</string>
@@ -655,8 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satelit, špatné připojení"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelit, dobré připojení"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, připojení je k dispozici"</string>
- <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"Připojeno k satelitu"</string>
- <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"Nepřipojeno k satelitu"</string>
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS přes satelit"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Pracovní profil"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Zábava, která není pro každého"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Nástroj na ladění uživatelského rozhraní systému vám nabízí další způsoby, jak si vyladit a přizpůsobit uživatelské rozhraní Android. Tyto experimentální funkce mohou v dalších verzích chybět, nefungovat nebo být změněny. Postupujte proto prosím opatrně."</string>
@@ -861,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Přidat dlaždici"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Přesunout na pozici <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Přidat dlaždici na pozici <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Pozice není platná."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Pozice <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Karta byla přidána"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Karta byla odstraněna"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index bee3563..036f855 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Venstre kant: <xliff:g id="PERCENT">%1$d</xliff:g> procent"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Højre kant: <xliff:g id="PERCENT">%1$d</xliff:g> procent"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Gemt i <xliff:g id="APP">%1$s</xliff:g> på arbejdsprofilen"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Gemt i <xliff:g id="APP">%1$s</xliff:g> på den private profil"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Filer"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> har registreret dette screenshot."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> og andre åbne apps har registreret dette screenshot."</string>
@@ -457,9 +458,13 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Vil du genoptage arbejdsapps?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Genoptag"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Luk widgets på låseskærmen"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Tilpas widgets"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widgets på låseskærmen"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"vælg widget"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Skift bruger"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"rullemenu"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alle apps og data i denne session slettes."</string>
@@ -589,7 +594,7 @@
<string name="screen_pinning_negative" msgid="6882816864569211666">"Nej tak"</string>
<string name="screen_pinning_start" msgid="7483998671383371313">"Appen er fastgjort"</string>
<string name="screen_pinning_exit" msgid="4553787518387346893">"Appen er frigjort"</string>
- <string name="stream_voice_call" msgid="7468348170702375660">"Ring op"</string>
+ <string name="stream_voice_call" msgid="7468348170702375660">"Opkald"</string>
<string name="stream_system" msgid="7663148785370565134">"System"</string>
<string name="stream_ring" msgid="7550670036738697526">"Ringetone"</string>
<string name="stream_music" msgid="2188224742361847580">"Medie"</string>
@@ -628,6 +633,7 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"slå lyden til for %s"</string>
<string name="media_output_label_title" msgid="872824698593182505">"Afspiller <xliff:g id="LABEL">%s</xliff:g> på"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"Lyden afspilles på"</string>
+ <string name="media_output_title_ongoing_call" msgid="208426888064112006">"Ringer på"</string>
<string name="system_ui_tuner" msgid="1471348823289954729">"System UI Tuner"</string>
<string name="status_bar" msgid="4357390266055077437">"Statusbjælke"</string>
<string name="demo_mode" msgid="263484519766901593">"Demotilstand for systemets brugerflade"</string>
@@ -655,10 +661,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satellit – dårlig forbindelse"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellit – god forbindelse"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellit – forbindelsen er tilgængelig"</string>
- <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
- <skip />
- <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
- <skip />
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS-meldinger via satellit"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Arbejdsprofil"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Sjovt for nogle, men ikke for alle"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner giver dig flere muligheder for at justere og tilpasse Android-brugerfladen. Disse eksperimentelle funktioner kan ændres, gå i stykker eller forsvinde i fremtidige udgivelser. Vær forsigtig, hvis du fortsætter."</string>
@@ -863,6 +866,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Tilføj felt"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Flyt til <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Føj til lokation <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Positionen er ugyldig."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Lokation <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Feltet blev tilføjet"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Feltet blev fjernet"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index e424363..42efdc2 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Linker Rand <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Rechter Rand <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"In <xliff:g id="APP">%1$s</xliff:g> im Arbeitsprofil gespeichert"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Im vertraulichen Profil in <xliff:g id="APP">%1$s</xliff:g> gespeichert"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Dateien"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> hat diesen Screenshot erkannt."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> und andere geöffnete Apps haben diesen Screenshot erkannt."</string>
@@ -457,9 +458,13 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Geschäftliche Apps nicht mehr pausieren?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Nicht mehr pausieren"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Widgets auf dem Sperrbildschirm schließen"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Widgets anpassen"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widgets auf dem Sperrbildschirm"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"Widget auswählen"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Nutzer wechseln"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"Pull-down-Menü"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alle Apps und Daten in dieser Sitzung werden gelöscht."</string>
@@ -628,6 +633,8 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"Stummschaltung von %s aufzuheben"</string>
<string name="media_output_label_title" msgid="872824698593182505">"Wiedergabe von <xliff:g id="LABEL">%s</xliff:g> über"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"Audiowiedergabe über"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"System UI Tuner"</string>
<string name="status_bar" msgid="4357390266055077437">"Statusleiste"</string>
<string name="demo_mode" msgid="263484519766901593">"Demomodus der System-UI"</string>
@@ -655,8 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satellit, Verbindung schlecht"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellit, Verbindung gut"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellit, Verbindung verfügbar"</string>
- <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"Mit Satellit verbunden"</string>
- <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"Nicht mit Satellit verbunden"</string>
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Notruf über Satellit"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Arbeitsprofil"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Für einige ein Vergnügen, aber nicht für alle"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Mit System UI Tuner erhältst du zusätzliche Möglichkeiten, die Android-Benutzeroberfläche anzupassen. Achtung: Diese Testfunktionen können sich ändern, abstürzen oder in zukünftigen Versionen verschwinden."</string>
@@ -861,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Kachel hinzufügen"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Auf Position <xliff:g id="POSITION">%1$d</xliff:g> verschieben"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Zur Position <xliff:g id="POSITION">%1$d</xliff:g> hinzufügen"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Position ist ungültig."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Position <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Ansicht hinzugefügt"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Ansicht entfernt"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index f8e0b53..72ab884 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Αριστερό όριο <xliff:g id="PERCENT">%1$d</xliff:g> τοις εκατό"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Δεξί όριο <xliff:g id="PERCENT">%1$d</xliff:g> τοις εκατό"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Αποθηκεύτηκε στην εφαρμογή <xliff:g id="APP">%1$s</xliff:g> στο προφίλ εργασίας"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Αποθηκεύτηκε στην εφαρμογή <xliff:g id="APP">%1$s</xliff:g> στο ιδιωτικό προφίλ"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Αρχεία"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"Η εφαρμογή <xliff:g id="APPNAME">%1$s</xliff:g> εντόπισε αυτό το στιγμιότυπο οθόνης."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"Η εφαρμογή <xliff:g id="APPNAME">%1$s</xliff:g> και άλλες ανοικτές εφαρμογές εντόπισαν το στιγμιότυπο οθόνης."</string>
@@ -457,9 +458,13 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Αναίρ. παύσης εφαρμ. εργασιών;"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Αναίρεση παύσης"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Κλείσιμο γραφικών στοιχείων στην οθόνη κλειδώματος"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Προσαρμογή γραφικών στοιχείων"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Γραφικά στοιχεία στην οθόνη κλειδώματος"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"επιλογή γραφικού στοιχείου"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Εναλλαγή χρήστη"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"αναπτυσσόμενο μενού"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Όλες οι εφαρμογές και τα δεδομένα αυτής της περιόδου σύνδεσης θα διαγραφούν."</string>
@@ -628,6 +633,8 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"κατάργηση σίγασης %s"</string>
<string name="media_output_label_title" msgid="872824698593182505">"Αναπαραγωγή <xliff:g id="LABEL">%s</xliff:g> σε"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"Ο ήχος θα παίξει σε"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"System UI Tuner"</string>
<string name="status_bar" msgid="4357390266055077437">"Γραμμή κατάστασης"</string>
<string name="demo_mode" msgid="263484519766901593">"Λειτουργία επίδειξης διεπαφής χρήστη συστήματος"</string>
@@ -655,8 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Δορυφορική, κακή σύνδεση"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Δορυφορική, καλή σύνδεση"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Δορυφορική, διαθέσιμη σύνδεση"</string>
- <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"Συνδέθηκε σε δορυφόρο"</string>
- <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"Δεν συνδέθηκε σε δορυφόρο"</string>
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Δορυφορικό SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Προφίλ εργασίας"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Διασκέδαση για ορισμένους, αλλά όχι για όλους"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Το System UI Tuner σάς προσφέρει επιπλέον τρόπους για να τροποποιήσετε και να προσαρμόσετε τη διεπαφή χρήστη Android. Αυτές οι πειραματικές λειτουργίες ενδέχεται να τροποποιηθούν, να παρουσιάσουν σφάλματα ή να καταργηθούν σε μελλοντικές εκδόσεις. Συνεχίστε με προσοχή."</string>
@@ -861,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Προσθήκη πλακιδίου"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Μετακίνηση στη θέση <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Προσθήκη στη θέση <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Μη έγκυρη θέση."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Θέση <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Το πλακίδιο προστέθηκε"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Το πλακίδιο καταργήθηκε"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 5a18245..e414cd4 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Left boundary <xliff:g id="PERCENT">%1$d</xliff:g> per cent"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Right boundary <xliff:g id="PERCENT">%1$d</xliff:g> per cent"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Saved in <xliff:g id="APP">%1$s</xliff:g> in the work profile"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Saved in <xliff:g id="APP">%1$s</xliff:g> in the private profile"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Files"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> detected this screenshot."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> and other open apps detected this screenshot."</string>
@@ -459,6 +460,11 @@
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Close widgets on lock screen"</string>
<string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Customise widgets"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widgets on lock screen"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"select widget"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Switch user"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"pulldown menu"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"All apps and data in this session will be deleted."</string>
@@ -627,6 +633,8 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"unmute %s"</string>
<string name="media_output_label_title" msgid="872824698593182505">"Playing <xliff:g id="LABEL">%s</xliff:g> on"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"Audio will play on"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"System UI Tuner"</string>
<string name="status_bar" msgid="4357390266055077437">"Status bar"</string>
<string name="demo_mode" msgid="263484519766901593">"System UI demo mode"</string>
@@ -654,10 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satellite, poor connection"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellite, good connection"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellite, connection available"</string>
- <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
- <skip />
- <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
- <skip />
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satellite SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Work profile"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Fun for some but not for all"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner gives you extra ways to tweak and customise the Android user interface. These experimental features may change, break or disappear in future releases. Proceed with caution."</string>
@@ -862,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Add tile"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Move to <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Add to position <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Position invalid."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Position <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Tile added"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Tile removed"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index 8b71d4b..204f21d 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Left boundary <xliff:g id="PERCENT">%1$d</xliff:g> percent"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Right boundary <xliff:g id="PERCENT">%1$d</xliff:g> percent"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Saved in <xliff:g id="APP">%1$s</xliff:g> in the work profile"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Saved in <xliff:g id="APP">%1$s</xliff:g> in the private profile"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Files"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> detected this screenshot."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> and other open apps detected this screenshot."</string>
@@ -459,6 +460,9 @@
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Close widgets on lock screen"</string>
<string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Customize widgets"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widgets on lock screen"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"select widget"</string>
+ <string name="accessibility_action_label_remove_widget" msgid="3373779447448758070">"remove widget"</string>
+ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"place selected widget"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Switch user"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"pulldown menu"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"All apps and data in this session will be deleted."</string>
@@ -627,6 +631,7 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"unmute %s"</string>
<string name="media_output_label_title" msgid="872824698593182505">"Playing <xliff:g id="LABEL">%s</xliff:g> on"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"Audio will play on"</string>
+ <string name="media_output_title_ongoing_call" msgid="208426888064112006">"Calling on"</string>
<string name="system_ui_tuner" msgid="1471348823289954729">"System UI Tuner"</string>
<string name="status_bar" msgid="4357390266055077437">"Status bar"</string>
<string name="demo_mode" msgid="263484519766901593">"System UI demo mode"</string>
@@ -654,8 +659,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satellite, poor connection"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellite, good connection"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellite, connection available"</string>
- <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"Connected to satellite"</string>
- <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"Not connected to satellite"</string>
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satellite SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Work profile"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Fun for some but not for all"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner gives you extra ways to tweak and customize the Android user interface. These experimental features may change, break, or disappear in future releases. Proceed with caution."</string>
@@ -860,6 +864,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Add tile"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Move to <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Add to position <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Position invalid."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Position <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Tile added"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Tile removed"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 5a18245..e414cd4 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Left boundary <xliff:g id="PERCENT">%1$d</xliff:g> per cent"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Right boundary <xliff:g id="PERCENT">%1$d</xliff:g> per cent"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Saved in <xliff:g id="APP">%1$s</xliff:g> in the work profile"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Saved in <xliff:g id="APP">%1$s</xliff:g> in the private profile"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Files"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> detected this screenshot."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> and other open apps detected this screenshot."</string>
@@ -459,6 +460,11 @@
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Close widgets on lock screen"</string>
<string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Customise widgets"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widgets on lock screen"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"select widget"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Switch user"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"pulldown menu"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"All apps and data in this session will be deleted."</string>
@@ -627,6 +633,8 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"unmute %s"</string>
<string name="media_output_label_title" msgid="872824698593182505">"Playing <xliff:g id="LABEL">%s</xliff:g> on"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"Audio will play on"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"System UI Tuner"</string>
<string name="status_bar" msgid="4357390266055077437">"Status bar"</string>
<string name="demo_mode" msgid="263484519766901593">"System UI demo mode"</string>
@@ -654,10 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satellite, poor connection"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellite, good connection"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellite, connection available"</string>
- <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
- <skip />
- <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
- <skip />
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satellite SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Work profile"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Fun for some but not for all"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner gives you extra ways to tweak and customise the Android user interface. These experimental features may change, break or disappear in future releases. Proceed with caution."</string>
@@ -862,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Add tile"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Move to <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Add to position <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Position invalid."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Position <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Tile added"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Tile removed"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 5a18245..e414cd4 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Left boundary <xliff:g id="PERCENT">%1$d</xliff:g> per cent"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Right boundary <xliff:g id="PERCENT">%1$d</xliff:g> per cent"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Saved in <xliff:g id="APP">%1$s</xliff:g> in the work profile"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Saved in <xliff:g id="APP">%1$s</xliff:g> in the private profile"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Files"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> detected this screenshot."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> and other open apps detected this screenshot."</string>
@@ -459,6 +460,11 @@
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Close widgets on lock screen"</string>
<string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Customise widgets"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widgets on lock screen"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"select widget"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Switch user"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"pulldown menu"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"All apps and data in this session will be deleted."</string>
@@ -627,6 +633,8 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"unmute %s"</string>
<string name="media_output_label_title" msgid="872824698593182505">"Playing <xliff:g id="LABEL">%s</xliff:g> on"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"Audio will play on"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"System UI Tuner"</string>
<string name="status_bar" msgid="4357390266055077437">"Status bar"</string>
<string name="demo_mode" msgid="263484519766901593">"System UI demo mode"</string>
@@ -654,10 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satellite, poor connection"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellite, good connection"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellite, connection available"</string>
- <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
- <skip />
- <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
- <skip />
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satellite SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Work profile"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Fun for some but not for all"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner gives you extra ways to tweak and customise the Android user interface. These experimental features may change, break or disappear in future releases. Proceed with caution."</string>
@@ -862,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Add tile"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Move to <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Add to position <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Position invalid."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Position <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Tile added"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Tile removed"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index f32b774..ee28a62 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Left boundary <xliff:g id="PERCENT">%1$d</xliff:g> percent"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Right boundary <xliff:g id="PERCENT">%1$d</xliff:g> percent"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Saved in <xliff:g id="APP">%1$s</xliff:g> in the work profile"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Saved in <xliff:g id="APP">%1$s</xliff:g> in the private profile"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Files"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> detected this screenshot."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> and other open apps detected this screenshot."</string>
@@ -459,6 +460,9 @@
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Close widgets on lock screen"</string>
<string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Customize widgets"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widgets on lock screen"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"select widget"</string>
+ <string name="accessibility_action_label_remove_widget" msgid="3373779447448758070">"remove widget"</string>
+ <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"place selected widget"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Switch user"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"pulldown menu"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"All apps and data in this session will be deleted."</string>
@@ -627,6 +631,7 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"unmute %s"</string>
<string name="media_output_label_title" msgid="872824698593182505">"Playing <xliff:g id="LABEL">%s</xliff:g> on"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"Audio will play on"</string>
+ <string name="media_output_title_ongoing_call" msgid="208426888064112006">"Calling on"</string>
<string name="system_ui_tuner" msgid="1471348823289954729">"System UI Tuner"</string>
<string name="status_bar" msgid="4357390266055077437">"Status bar"</string>
<string name="demo_mode" msgid="263484519766901593">"System UI demo mode"</string>
@@ -654,8 +659,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satellite, poor connection"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellite, good connection"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellite, connection available"</string>
- <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"Connected to satellite"</string>
- <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"Not connected to satellite"</string>
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satellite SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Work profile"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Fun for some but not for all"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner gives you extra ways to tweak and customize the Android user interface. These experimental features may change, break, or disappear in future releases. Proceed with caution."</string>
@@ -860,6 +864,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Add tile"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Move to <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Add to position <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Position invalid."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Position <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Tile added"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Tile removed"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 552f31f..42424ef 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Límite izquierdo: <xliff:g id="PERCENT">%1$d</xliff:g> por ciento"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Límite derecho: <xliff:g id="PERCENT">%1$d</xliff:g> por ciento"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Se guardó en <xliff:g id="APP">%1$s</xliff:g> en el perfil de trabajo"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Guardada en <xliff:g id="APP">%1$s</xliff:g> en el perfil personal"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Archivos"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> detectó que tomaste una captura de pantalla."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> y otras apps en ejecución detectaron que tomaste una captura de pantalla."</string>
@@ -274,7 +275,7 @@
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Guardado"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"desconectar"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activar"</string>
- <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Volver a activar automáticamente mañana"</string>
+ <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Activar automáticamente mañana"</string>
<string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Las funciones como Quick Share y Encontrar mi dispositivo usan Bluetooth"</string>
<string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"El Bluetooth se activará mañana a la mañana"</string>
<string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Uso compartido de audio"</string>
@@ -457,9 +458,13 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"¿Reanudar apps de trabajo?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Reanudar"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Cerrar widgets en la pantalla de bloqueo"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Personalizar widgets"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widgets en la pantalla de bloqueo"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"Seleccionar widget"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Cambiar usuario"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menú expandible"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Se eliminarán las aplicaciones y los datos de esta sesión."</string>
@@ -628,6 +633,8 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"activar sonido %s"</string>
<string name="media_output_label_title" msgid="872824698593182505">"Reproduciendo <xliff:g id="LABEL">%s</xliff:g> en"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"Se reproducirá en"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"Sintonizador de IU del sistema"</string>
<string name="status_bar" msgid="4357390266055077437">"Barra de estado"</string>
<string name="demo_mode" msgid="263484519766901593">"Modo demostración de la IU del sistema"</string>
@@ -655,10 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satélite, conexión inestable"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satélite, buena conexión"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satélite, conexión disponible"</string>
- <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
- <skip />
- <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
- <skip />
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS por satélite"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Perfil de trabajo"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Diversión para algunos, pero no para todos"</string>
<string name="tuner_warning" msgid="1861736288458481650">"El sintonizador de IU del sistema te brinda más formas para editar y personalizar la interfaz de usuario de Android. Estas funciones experimentales pueden cambiar, dejar de funcionar o no incluirse en futuras versiones. Procede con precaución."</string>
@@ -863,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Agregar tarjeta"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Mover a <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Agregar a la posición <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Posición no válida"</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Posición <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Se agregó la tarjeta"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Se quitó la tarjeta"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 10f480e..77989e4 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"<xliff:g id="PERCENT">%1$d</xliff:g> por ciento del límite izquierdo"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"<xliff:g id="PERCENT">%1$d</xliff:g> por ciento del límite derecho"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Se ha guardado en el perfil de trabajo de <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Se ha guardado en el perfil privado de <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Archivos"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> ha detectado esta captura de pantalla."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> y otras aplicaciones abiertas han detectado esta captura de pantalla."</string>
@@ -457,9 +458,13 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"¿Reactivar apps de trabajo?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Reactivar"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Cerrar widgets en la pantalla de bloqueo"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Personalizar widgets"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widgets en la pantalla de bloqueo"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"seleccionar widget"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Cambiar de usuario"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menú desplegable"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Se eliminarán todas las aplicaciones y datos de esta sesión."</string>
@@ -628,6 +633,8 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"dejar de silenciar %s"</string>
<string name="media_output_label_title" msgid="872824698593182505">"Reproduciendo <xliff:g id="LABEL">%s</xliff:g> en"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"Se reproducirá en"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"Configurador de UI del sistema"</string>
<string name="status_bar" msgid="4357390266055077437">"Barra de estado"</string>
<string name="demo_mode" msgid="263484519766901593">"Modo Demo de UI del sistema"</string>
@@ -655,10 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satélite, mala conexión"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satélite, buena conexión"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satélite, conexión disponible"</string>
- <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
- <skip />
- <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
- <skip />
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS por satélite"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Perfil de trabajo"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Diversión solo para algunos"</string>
<string name="tuner_warning" msgid="1861736288458481650">"El configurador de UI del sistema te ofrece otras formas de modificar y personalizar la interfaz de usuario de Android. Estas funciones experimentales pueden cambiar, fallar o desaparecer en futuras versiones. Te recomendamos que tengas cuidado."</string>
@@ -863,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Añadir recuadro"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Mover a <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Añadir a la posición <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Posición no válida."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Posición <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Recuadro añadido"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Recuadro quitado"</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 0f98ce68..a3663a0 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Vasak piir: <xliff:g id="PERCENT">%1$d</xliff:g> protsenti"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Parem piir: <xliff:g id="PERCENT">%1$d</xliff:g> protsenti"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Salvestati tööprofiilil rakendusse <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Salvestati privaatsel profiilil rakendusse <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Files"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> tuvastas selle ekraanipildi."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> ja muud avatud rakendused tuvastasid selle ekraanipildi."</string>
@@ -459,6 +460,11 @@
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Lukustuskuva vidinate sulgemine"</string>
<string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Kohanda vidinaid"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Lukustuskuva vidinad"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"vidina valimine"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Kasutaja vahetamine"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"rippmenüü"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Seansi kõik rakendused ja andmed kustutatakse."</string>
@@ -627,6 +633,8 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"tühistab %s vaigistuse"</string>
<string name="media_output_label_title" msgid="872824698593182505">"Esitamine jätkub seadmes <xliff:g id="LABEL">%s</xliff:g>"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"Heli esitatakse seadmes"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"Süsteemi kasutajaliidese tuuner"</string>
<string name="status_bar" msgid="4357390266055077437">"Olekuriba"</string>
<string name="demo_mode" msgid="263484519766901593">"Süsteemi kasutajaliidese demorežiim"</string>
@@ -654,10 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satelliit, kehv ühendus"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelliit, hea ühendus"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelliit, ühendus on saadaval"</string>
- <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
- <skip />
- <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
- <skip />
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satelliit-SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Tööprofiil"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Kõik ei pruugi sellest rõõmu tunda"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Süsteemi kasutajaliidese tuuner pakub täiendavaid võimalusi Androidi kasutajaliidese muutmiseks ja kohandamiseks. Need katselised funktsioonid võivad muutuda, rikki minna või tulevastest versioonidest kaduda. Olge jätkamisel ettevaatlik."</string>
@@ -862,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Lisa paan"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Teisaldamine asendisse <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Lisamine asendisse <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Sobimatu asukoht."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Asend <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Paan on lisatud"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Paan on eemaldatud"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 393aa97..23de72e 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Ezkerreko ertza: ehuneko <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Eskuineko ertza: ehuneko <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Laneko profilaren <xliff:g id="APP">%1$s</xliff:g> aplikazioan gorde da"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Profil pribatuaren <xliff:g id="APP">%1$s</xliff:g> aplikazioan gorde da"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Fitxategiak"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> aplikazioak pantaila-argazkia hauteman du."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> aplikazioak eta irekitako beste aplikazio batzuek pantaila-argazkia hauteman dute."</string>
@@ -457,9 +458,13 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Laneko aplikazioak berraktibatu?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Berraktibatu"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Itxi pantaila blokeatuko widgetak"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Pertsonalizatu widgetak"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Pantaila blokeatuko widgetak"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"hautatu widget bat"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Aldatu erabiltzailea"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"zabaldu menua"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Saioko aplikazio eta datu guztiak ezabatuko dira."</string>
@@ -628,6 +633,8 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"aktibatu honen audioa: %s"</string>
<string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> hemen erreproduzitzen:"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"Audioak abian jarraituko du hemen:"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"Sistemaren erabiltzaile-interfazearen konfiguratzailea"</string>
<string name="status_bar" msgid="4357390266055077437">"Egoera-barra"</string>
<string name="demo_mode" msgid="263484519766901593">"Sistemaren erabiltzaile-interfazearen demo modua"</string>
@@ -655,10 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satelitea, konexio ahula"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelitea, konexio ona"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelitea, konexioa erabilgarri"</string>
- <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
- <skip />
- <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
- <skip />
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satelite bidezko SOS komunikazioa"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Laneko profila"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Dibertsioa batzuentzat, baina ez guztientzat"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Sistemaren erabiltzaile-interfazearen konfiguratzaileak Android erabiltzaile-interfazea moldatzeko eta pertsonalizatzeko modu gehiago eskaintzen dizkizu. Baliteke eginbide esperimental horiek hurrengo kaleratzeetan aldatuta, etenda edo desagertuta egotea. Kontuz erabili."</string>
@@ -773,8 +777,8 @@
<string name="group_system_go_back" msgid="2730322046244918816">"Egin atzera"</string>
<string name="group_system_access_home_screen" msgid="4130366993484706483">"Joan orri nagusira"</string>
<string name="group_system_overview_open_apps" msgid="5659958952937994104">"Ikusi azkenaldiko aplikazioak"</string>
- <string name="group_system_cycle_forward" msgid="5478663965957647805">"Ikusi azken aplikazioak banan-banan (aurrerantz)"</string>
- <string name="group_system_cycle_back" msgid="8194102916946802902">"Ikusi azken aplikazioak banan-banan (atzerantz)"</string>
+ <string name="group_system_cycle_forward" msgid="5478663965957647805">"Ikusi azkenaldiko aplikazioak banan-banan (aurrerantz)"</string>
+ <string name="group_system_cycle_back" msgid="8194102916946802902">"Ikusi azkenaldiko aplikazioak banan-banan (atzerantz)"</string>
<string name="group_system_access_all_apps_search" msgid="1553588630154197469">"Ireki aplikazioen zerrenda"</string>
<string name="group_system_access_system_settings" msgid="8731721963449070017">"Ireki ezarpenak"</string>
<string name="group_system_access_google_assistant" msgid="7210074957915968110">"Ireki Laguntzailea"</string>
@@ -863,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Gehitu lauza"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Eraman <xliff:g id="POSITION">%1$d</xliff:g>garren lekura"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Gehitu <xliff:g id="POSITION">%1$d</xliff:g>garren lekuan"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Kokapenak ez du balio."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"<xliff:g id="POSITION">%1$d</xliff:g>garren lekua"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Gehitu da lauza"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Kendu da lauza"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 10ff0db..9feeaee 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -21,7 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"واسط کاربری سیستم"</string>
<string name="battery_low_title" msgid="5319680173344341779">"«بهینهسازی باتری» روشن شود؟"</string>
- <string name="battery_low_description" msgid="3282977755476423966">"<xliff:g id="PERCENTAGE">%s</xliff:g> از باتریتان باقی مانده است. «بهینهسازی باتری» زمینه تیره را روشن میکند، فعالیتهای پسزمینه را محدود میکند، و اعلانها را بهتأخیر میاندازد."</string>
+ <string name="battery_low_description" msgid="3282977755476423966">"<xliff:g id="PERCENTAGE">%s</xliff:g> از باتریتان باقی مانده است. «بهینهسازی باتری» زمینه تاریک را روشن میکند، فعالیتهای پسزمینه را محدود میکند، و اعلانها را بهتأخیر میاندازد."</string>
<string name="battery_low_intro" msgid="5148725009653088790">"«بهینهسازی باتری» زمینه «تیره» را روشن میکند، فعالیتهای پسزمینه را محدود میکند، و اعلانها را بهتأخیر میاندازد."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> باقی مانده است"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"ازطریق USB شارژ نمیشود"</string>
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"مرز سمت چپ <xliff:g id="PERCENT">%1$d</xliff:g> درصد"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"مرز سمت راست <xliff:g id="PERCENT">%1$d</xliff:g> درصد"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"در برنامه <xliff:g id="APP">%1$s</xliff:g> در نمایه کاری ذخیره شد"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"در برنامه <xliff:g id="APP">%1$s</xliff:g> در نمایه خصوصی ذخیره شد"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Files"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"«<xliff:g id="APPNAME">%1$s</xliff:g>» این نماگرفت را تشخیص داد."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> و سایر برنامههای باز این نماگرفت را تشخیص دادند."</string>
@@ -187,7 +188,7 @@
<string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"اگر در تلاش بعدی پین نادرستی وارد کنید، نمایه کاری شما و دادههای آن حذف خواهند شد."</string>
<string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"اگر در تلاش بعدی گذرواژه نادرستی وارد کنید، نمایه کاری شما و دادههای آن حذف خواهند شد."</string>
<string name="biometric_re_enroll_dialog_confirm" msgid="3049858021857801836">"راهاندازی"</string>
- <string name="biometric_re_enroll_dialog_cancel" msgid="93760939407091417">"اکنون نه"</string>
+ <string name="biometric_re_enroll_dialog_cancel" msgid="93760939407091417">"حالا نه"</string>
<string name="biometric_re_enroll_notification_content" msgid="8685925877186288180">"این کار برای بهبود امنیت و عملکرد لازم است"</string>
<string name="fingerprint_re_enroll_notification_title" msgid="4539432429683916604">"راهاندازی مجدد «قفلگشایی با اثر انگشت»"</string>
<string name="fingerprint_re_enroll_notification_name" msgid="630798657797645704">"قفلگشایی با اثر انگشت"</string>
@@ -336,7 +337,7 @@
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"تا طلوع"</string>
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"ساعت <xliff:g id="TIME">%s</xliff:g> روشن میشود"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"تا <xliff:g id="TIME">%s</xliff:g>"</string>
- <string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"زمینه تیره"</string>
+ <string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"زمینه تاریک"</string>
<string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"بهینهسازی باتری"</string>
<string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"غروب روشن میشود"</string>
<string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"تا طلوع آفتاب"</string>
@@ -457,9 +458,13 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"مکث برنامههای کاری لغو شود؟"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"لغو مکث"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"بستن ابزارکها در صفحه قفل"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"سفارشیسازی ابزارکها"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"ابزارکها در صفحه قفل"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"انتخاب ابزارک"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"تغییر کاربر"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"منوی پایینپر"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"همه برنامهها و دادههای این جلسه حذف خواهد شد."</string>
@@ -628,6 +633,8 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"باصدا کردن %s"</string>
<string name="media_output_label_title" msgid="872824698593182505">"درحال پخش <xliff:g id="LABEL">%s</xliff:g> در"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"صدا در این دستگاه پخش میشود:"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"تنظیمکننده واسط کاربری سیستم"</string>
<string name="status_bar" msgid="4357390266055077437">"نوار وضعیت"</string>
<string name="demo_mode" msgid="263484519766901593">"حالت نمایشی واسط کاربری سیستم"</string>
@@ -655,8 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"ماهواره، اتصال ضعیف است"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"ماهواره، اتصال خوب است"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ماهواره، اتصال دردسترس است"</string>
- <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"به ماهواره متصل هستید"</string>
- <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"به ماهواره متصل نیستید"</string>
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"درخواست کمک ماهوارهای"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"نمایه کاری"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"برای بعضی افراد سرگرمکننده است اما نه برای همه"</string>
<string name="tuner_warning" msgid="1861736288458481650">"«تنظیمکننده واسط کاربری سیستم» روشهای بیشتری برای تنظیم دقیق و سفارشی کردن واسط کاربری Android در اختیار شما قرار میدهد. ممکن است این ویژگیهای آزمایشی تغییر کنند، خراب شوند یا در نسخههای آینده جود نداشته باشند. با احتیاط ادامه دهید."</string>
@@ -861,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"افزودن کاشی"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"انتقال به <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"افزودن به موقعیت <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"موقعیت نامعتبر است."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"موقعیت <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"کاشی اضافه شد"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"کاشی حذف شد"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index bc761e7..68319fd 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Vasen reuna <xliff:g id="PERCENT">%1$d</xliff:g> prosenttia"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Oikea reuna <xliff:g id="PERCENT">%1$d</xliff:g> prosenttia"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Tallennettu työprofiiliin tässä sovelluksessa: <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Tallennettu yksityiseen profiiliin tässä sovelluksessa: <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Files"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> havaitsi tämän kuvakaappauksen."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> ja jotkin muut sovellukset havaitsivat tämän kuvakaappauksen."</string>
@@ -457,9 +458,13 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Laita työsovellukset päälle?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Laita päälle"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Sulje widgetit lukitusnäytöllä"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Muokkaa widgetejä"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widgetit lukitusnäytöllä"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"valitse widget"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Vaihda käyttäjää"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"alasvetovalikko"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Kaikki sovellukset ja tämän istunnon tiedot poistetaan."</string>
@@ -628,6 +633,8 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"poista mykistys: %s"</string>
<string name="media_output_label_title" msgid="872824698593182505">"Toistetaan: <xliff:g id="LABEL">%s</xliff:g>"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"Audiota toistetaan laitteella"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"System UI Tuner"</string>
<string name="status_bar" msgid="4357390266055077437">"Tilapalkki"</string>
<string name="demo_mode" msgid="263484519766901593">"Käyttöliittymän esittelytila"</string>
@@ -655,8 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satelliitti, huono yhteys"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelliitti, hyvä yhteys"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelliitti, yhteys saatavilla"</string>
- <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"Yhteys satelliittiin"</string>
- <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"Ei yhteyttä satelliittiin"</string>
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satellite SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Työprofiili"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Ei sovellu kaikkien käyttöön"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner antaa lisämahdollisuuksia Android-käyttöliittymän muokkaamiseen. Nämä kokeelliset ominaisuudet voivat muuttua, lakata toimimasta tai kadota milloin tahansa. Jatka omalla vastuullasi."</string>
@@ -861,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Lisää kiekko"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Siirrä paikkaan <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Lisää paikkaan <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Virheellinen sijainti."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Paikka <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Kiekko lisätty"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Kiekko poistettu"</string>
@@ -916,7 +923,7 @@
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="mobile_carrier_text_format" msgid="8912204177152950766">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="MOBILE_DATA_TYPE">%2$s</xliff:g>"</string>
<string name="wifi_is_off" msgid="5389597396308001471">"Wi-Fi on pois päältä"</string>
- <string name="bt_is_off" msgid="7436344904889461591">"Bluetooth ei ole käytössä"</string>
+ <string name="bt_is_off" msgid="7436344904889461591">"Bluetooth on pois päältä"</string>
<string name="dnd_is_off" msgid="3185706903793094463">"Älä häiritse ‑tila on pois päältä"</string>
<string name="dnd_is_on" msgid="7009368176361546279">"Älä häiritse ‑tila on käytössä"</string>
<string name="qs_dnd_prompt_auto_rule" msgid="3535469468310002616">"Automaattinen sääntö otti käyttöön Älä häiritse ‑tilan (<xliff:g id="ID_1">%s</xliff:g>)."</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index f039c83..fd6ec7a 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -20,13 +20,13 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4811759950673118541">"IU système"</string>
- <string name="battery_low_title" msgid="5319680173344341779">"Activer l\'économiseur de pile?"</string>
+ <string name="battery_low_title" msgid="5319680173344341779">"Activer l\'Économiseur de pile?"</string>
<string name="battery_low_description" msgid="3282977755476423966">"Il vous reste <xliff:g id="PERCENTAGE">%s</xliff:g> d\'autonomie. L\'économiseur de pile active le thème sombre, limite l\'activité en arrière-plan et retarde les notifications."</string>
<string name="battery_low_intro" msgid="5148725009653088790">"L\'économiseur de pile active le thème sombre, limite l\'activité en arrière-plan et retarde les notifications."</string>
<string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> restants"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"Impossible de charger l\'appareil par USB"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Servez-vous du chargeur fourni avec votre appareil"</string>
- <string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Activer l\'économiseur de pile?"</string>
+ <string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Activer l\'Économiseur de pile?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"À propos du mode Économiseur de pile"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Activer"</string>
<string name="battery_saver_start_action" msgid="8353766979886287140">"Activer"</string>
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Limite gauche : <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Limite droite : <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Enregistré dans <xliff:g id="APP">%1$s</xliff:g> dans le profil professionnel"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Enregistré dans <xliff:g id="APP">%1$s</xliff:g> dans le profil privé"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Fichiers"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> a détecté cette capture d\'écran."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> et d\'autres applications ouvertes ont détecté cette capture d\'écran."</string>
@@ -459,6 +460,11 @@
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Fermer les widgets sur l\'écran de verrouillage"</string>
<string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Personnaliser les widgets"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widgets sur l\'écran de verrouillage"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"sélectionner le widget"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Changer d\'utilisateur"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu déroulant"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Toutes les applications et les données de cette session seront supprimées."</string>
@@ -627,6 +633,8 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"Réactivez le son de %s"</string>
<string name="media_output_label_title" msgid="872824698593182505">"Lecture de <xliff:g id="LABEL">%s</xliff:g> sur"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"Lecture audio sur"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"System UI Tuner"</string>
<string name="status_bar" msgid="4357390266055077437">"Barre d\'état"</string>
<string name="demo_mode" msgid="263484519766901593">"Mode Démo de l\'interface système"</string>
@@ -654,8 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Connexion satellite faible"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Bonne connexion satellite"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Connexion satellite accessible"</string>
- <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"Connecté au satellite"</string>
- <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"Non connecté au satellite"</string>
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS par satellite"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Profil professionnel"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Divertissant pour certains, mais pas pour tous"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner vous propose de nouvelles manières d\'adapter et de personnaliser l\'interface utilisateur d\'Android. Ces fonctionnalités expérimentales peuvent être modifiées, cesser de fonctionner ou disparaître dans les versions futures. À utiliser avec prudence."</string>
@@ -860,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Ajouter la tuile"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Déplacer vers <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Ajouter à la position <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Position incorrecte."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Position <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Tuile ajoutée"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Tuile retirée"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 0df8988..47f469f 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Limite gauche : <xliff:g id="PERCENT">%1$d</xliff:g> pour cent"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Limite droite : <xliff:g id="PERCENT">%1$d</xliff:g> pour cent"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Enregistré dans <xliff:g id="APP">%1$s</xliff:g>, dans le profil professionnel"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Enregistré dans <xliff:g id="APP">%1$s</xliff:g> dans le profil privé"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Fichiers"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> a détecté cette capture d\'écran."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> et d\'autres applis ouvertes ont détecté cette capture d\'écran."</string>
@@ -265,7 +266,7 @@
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Ne pas déranger"</string>
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Aucun appareil associé disponible."</string>
- <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Appuyer pour connecter ou déconnecter un appareil"</string>
+ <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Appuyez pour connecter ou déconnecter un appareil"</string>
<string name="pair_new_bluetooth_devices" msgid="4601767620843349645">"Associer un nouvel appareil"</string>
<string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Tout afficher"</string>
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Utiliser le Bluetooth"</string>
@@ -367,7 +368,7 @@
<string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standard"</string>
<string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Moyen"</string>
<string name="quick_settings_contrast_high" msgid="656049259587494499">"Élevé"</string>
- <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Prothèses auditives"</string>
+ <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Appareils auditifs"</string>
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Appareils auditifs"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Associer un nouvel appareil"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Cliquer pour associer un nouvel appareil"</string>
@@ -457,9 +458,13 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Réactiver les applis pro ?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Réactiver"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Fermer les widgets sur l\'écran de verrouillage"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Personnaliser les widgets"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widgets sur l\'écran de verrouillage"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"sélectionner un widget"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Changer d\'utilisateur"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu déroulant"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Toutes les applications et les données de cette session seront supprimées."</string>
@@ -628,6 +633,7 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"réactiver le son de %s"</string>
<string name="media_output_label_title" msgid="872824698593182505">"Diffusion de <xliff:g id="LABEL">%s</xliff:g> sur"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"Lecture audio sur"</string>
+ <string name="media_output_title_ongoing_call" msgid="208426888064112006">"Appel défini sur"</string>
<string name="system_ui_tuner" msgid="1471348823289954729">"System UI Tuner"</string>
<string name="status_bar" msgid="4357390266055077437">"Barre d\'état"</string>
<string name="demo_mode" msgid="263484519766901593">"Mode démo de l\'UI du système"</string>
@@ -655,10 +661,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Mauvaise connexion satellite"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Bonne connexion satellite"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Connexion satellite disponible"</string>
- <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
- <skip />
- <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
- <skip />
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS par satellite"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Profil professionnel"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Divertissant pour certains, mais pas pour tous"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner vous propose de nouvelles manières d\'adapter et de personnaliser l\'interface utilisateur Android. Ces fonctionnalités expérimentales peuvent être modifiées, cesser de fonctionner ou disparaître dans les versions futures. À utiliser avec prudence."</string>
@@ -863,6 +866,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Ajouter un bloc"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Déplacer vers <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Ajouter à la position <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Emplacement non valide."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Position <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Bloc ajouté"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Bloc supprimé"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 4682c02..e7037b3 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Bordo esquerdo: <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Bordo dereito: <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Captura de pantalla gardada na aplicación <xliff:g id="APP">%1$s</xliff:g> do perfil de traballo"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Gardouse na aplicación <xliff:g id="APP">%1$s</xliff:g> do perfil privado"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Ficheiros"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> detectou esta captura de pantalla."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> e outras aplicacións abertas detectaron esta captura de pantalla."</string>
@@ -369,7 +370,7 @@
<string name="quick_settings_contrast_high" msgid="656049259587494499">"Nivel alto"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Dispositivos auditivos"</string>
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Dispositivos auditivos"</string>
- <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Vincular un dispositivo novo"</string>
+ <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Vincular dispositivo novo"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Fai clic para vincular un novo dispositivo"</string>
<string name="hearing_devices_presets_error" msgid="350363093458408536">"Non se puido actualizar a configuración predeterminada"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Queres desbloquear o micrófono do dispositivo?"</string>
@@ -457,9 +458,13 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Reactivar apps do traballo?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Reactivar"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Ocultar os widgets na pantalla de bloqueo"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Personalizar os widgets"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widgets na pantalla de bloqueo"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"seleccionar widget"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Cambiar usuario"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menú despregable"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Eliminaranse todas as aplicacións e datos desta sesión."</string>
@@ -591,7 +596,7 @@
<string name="screen_pinning_exit" msgid="4553787518387346893">"Deixouse de fixar a aplicación"</string>
<string name="stream_voice_call" msgid="7468348170702375660">"Chamada"</string>
<string name="stream_system" msgid="7663148785370565134">"Sistema"</string>
- <string name="stream_ring" msgid="7550670036738697526">"Son"</string>
+ <string name="stream_ring" msgid="7550670036738697526">"Ton"</string>
<string name="stream_music" msgid="2188224742361847580">"Multimedia"</string>
<string name="stream_alarm" msgid="16058075093011694">"Alarma"</string>
<string name="stream_notification" msgid="7930294049046243939">"Notificación"</string>
@@ -628,6 +633,8 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"activar o son de %s"</string>
<string name="media_output_label_title" msgid="872824698593182505">"Reproducindo <xliff:g id="LABEL">%s</xliff:g> en"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"Reproducirase en"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"Configurador da IU do sistema"</string>
<string name="status_bar" msgid="4357390266055077437">"Barra de estado"</string>
<string name="demo_mode" msgid="263484519766901593">"Modo de demostración da IU do sistema"</string>
@@ -655,10 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satélite, mala conexión"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satélite, boa conexión"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satélite, conexión dispoñible"</string>
- <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
- <skip />
- <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
- <skip />
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS por satélite"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Perfil de traballo"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Diversión só para algúns"</string>
<string name="tuner_warning" msgid="1861736288458481650">"O configurador da IU do sistema ofréceche formas adicionais de modificar e personalizar a interface de usuario de Android. Estas funcións experimentais poden cambiar, interromperse ou desaparecer en futuras versións. Continúa con precaución."</string>
@@ -863,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Engadir tarxeta"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Mover a <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Engadir á posición <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Posición non válida."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Posición <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Engadiuse a tarxeta"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Quitouse a tarxeta"</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 0e03bcf..b3c8e1eb 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"ડાબી બાજુની સીમા <xliff:g id="PERCENT">%1$d</xliff:g> ટકા"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"જમણી બાજુની સીમા <xliff:g id="PERCENT">%1$d</xliff:g> ટકા"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"ઑફિસની પ્રોફાઇલમાં <xliff:g id="APP">%1$s</xliff:g>માં સાચવવામાં આવ્યો"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"<xliff:g id="APP">%1$s</xliff:g>માં ખાનગી પ્રોફાઇલમાં સાચવવામાં આવ્યો"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"ફાઇલો"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> દ્વારા આ સ્ક્રીનશૉટ લેવાયાની ભાળ મેળવવામાં આવી."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> અને કામ કરતી અન્ય ઍપ દ્વારા આ સ્ક્રીનશૉટ લેવાયાની ભાળ મેળવવામાં આવી."</string>
@@ -459,6 +460,11 @@
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"લૉક સ્ક્રીન પર વિજેટ બંધ કરો"</string>
<string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"વિજેટ કસ્ટમાઇઝ કરો"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"લૉક સ્ક્રીન પર વિજેટ"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"વિજેટ પસંદ કરો"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"વપરાશકર્તા સ્વિચ કરો"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"પુલડાઉન મેનૂ"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"આ સત્રમાંની તમામ ઍપ અને ડેટા કાઢી નાખવામાં આવશે."</string>
@@ -627,6 +633,7 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"%sને અનમ્યૂટ કરો"</string>
<string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> વગાડી રહ્યાં છીએ"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"ઑડિયો આની પર વાગશે"</string>
+ <string name="media_output_title_ongoing_call" msgid="208426888064112006">"કૉલ ચાલુ છે"</string>
<string name="system_ui_tuner" msgid="1471348823289954729">"સિસ્ટમ UI ટ્યૂનર"</string>
<string name="status_bar" msgid="4357390266055077437">"સ્ટેટસ બાર"</string>
<string name="demo_mode" msgid="263484519766901593">"સિસ્ટમ UI ડેમો મોડ"</string>
@@ -654,8 +661,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"સૅટલાઇટ, નબળું કનેક્શન"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"સૅટલાઇટ, સારું કનેક્શન"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"સૅટલાઇટ, કનેક્શન ઉપલબ્ધ છે"</string>
- <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"સૅટલાઇટ સાથે કનેક્ટેડ છે"</string>
- <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"સૅટલાઇટ સાથે કનેક્ટેડ નથી"</string>
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"ઇમર્જન્સી સૅટલાઇટ સહાય"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"ઑફિસની પ્રોફાઇલ"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"કેટલાક માટે મજા પરંતુ બધા માટે નહીં"</string>
<string name="tuner_warning" msgid="1861736288458481650">"સિસ્ટમ UI ટ્યૂનર તમને Android વપરાશકર્તા ઇન્ટરફેસને ટ્વીક અને કસ્ટમાઇઝ કરવાની વધારાની રીતો આપે છે. ભાવિ રીલિઝેસમાં આ પ્રાયોગિક સુવિધાઓ બદલાઈ, ભંગ અથવા અદૃશ્ય થઈ શકે છે. સાવધાની સાથે આગળ વધો."</string>
@@ -860,6 +866,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"ટાઇલ ઉમેરો"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g> પર ખસેડો"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"જગ્યા પર <xliff:g id="POSITION">%1$d</xliff:g> ઉમેરો"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"સ્થિતિ અમાન્ય છે."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"જગ્યા <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"ટાઇલ ઉમેરી"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"ટાઇલ કાઢી નાખી"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 2186143..2882584 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"बाएं किनारे से <xliff:g id="PERCENT">%1$d</xliff:g> प्रतिशत"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"दाएं किनारे से <xliff:g id="PERCENT">%1$d</xliff:g> प्रतिशत"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"वर्क प्रोफ़ाइल में मौजूद <xliff:g id="APP">%1$s</xliff:g> में सेव किया गया है"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"स्क्रीनशॉट को <xliff:g id="APP">%1$s</xliff:g> की निजी प्रोफ़ाइल में सेव किया गया"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Files"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> को इस स्क्रीनशॉट का पता चला है."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> और खुले हुए अन्य ऐप्लिकेशन को इस स्क्रीनशॉट का पता चला है."</string>
@@ -274,7 +275,7 @@
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"सेव किया गया"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"डिसकनेक्ट करें"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"चालू करें"</string>
- <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"कल फिर से अपने-आप चालू हो जाएगा"</string>
+ <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"कल फिर से अपने-आप चालू हो जाए"</string>
<string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"क्विक शेयर और Find My Device जैसी सुविधाएं, ब्लूटूथ का इस्तेमाल करती हैं"</string>
<string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"ब्लूटूथ कल सुबह चालू होगा"</string>
<string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"ऑडियो शेयर करने की सुविधा"</string>
@@ -459,6 +460,11 @@
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"लॉक स्क्रीन पर विजेट बंद करें"</string>
<string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"विजेट अपनी पसंद के मुताबिक बनाएं"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"लॉक स्क्रीन पर विजेट"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"विजेट चुनें"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"उपयोगकर्ता बदलें"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"पुलडाउन मेन्यू"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"इस सेशन के सभी ऐप्लिकेशन और डेटा को हटा दिया जाएगा."</string>
@@ -625,8 +631,10 @@
<string name="volume_panel_collapsed_sliders" msgid="1413383759434791450">"आवाज़ के स्लाइडर को छोटा किया गया"</string>
<string name="volume_panel_hint_mute" msgid="6962563028495243738">"%s को म्यूट करें"</string>
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"%s को अनम्यूट करें"</string>
- <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> को चलाया जा रहा है"</string>
+ <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> इस पर चल रहा है"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"ऑडियो इस पर चलेगा"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"सिस्टम यूज़र इंटरफ़ेस (यूआई) ट्यूनर"</string>
<string name="status_bar" msgid="4357390266055077437">"स्टेटस बार"</string>
<string name="demo_mode" msgid="263484519766901593">"सिस्टम यूज़र इंटरफ़ेस (यूआई) डेमो मोड"</string>
@@ -654,8 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"सैटलाइट कनेक्शन खराब है"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"सैटलाइट कनेक्शन अच्छा है"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"सैटलाइट कनेक्शन उपलब्ध है"</string>
- <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"सैटलाइट सिग्नल से कनेक्ट है"</string>
- <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"सैटलाइट सिग्नल से कनेक्ट नहीं है"</string>
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"सैटलाइट एसओएस"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"वर्क प्रोफ़ाइल"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"कुछ के लिए मज़ेदार लेकिन सबके लिए नहीं"</string>
<string name="tuner_warning" msgid="1861736288458481650">"सिस्टम यूज़र इंटरफ़ेस (यूआई) ट्यूनर, आपको Android यूज़र इंटरफ़ेस में सुधार लाने और उसे अपनी पसंद के हिसाब से बदलने के कुछ और तरीके देता है. प्रयोग के तौर पर इस्तेमाल हो रहीं ये सुविधाएं आगे चल कर रिलीज़ की जा सकती हैं, रोकी जा सकती हैं या दिखाई देना बंद हो सकती हैं. सावधानी से आगे बढ़ें."</string>
@@ -860,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"टाइल जोड़ें"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"टाइल को <xliff:g id="POSITION">%1$d</xliff:g> पोज़िशन पर ले जाएं"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"टाइल को <xliff:g id="POSITION">%1$d</xliff:g> पोज़िशन पर जोड़ें"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"मौजूदा जगह अमान्य है."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"टाइल की पोज़िशन <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"टाइल जोड़ी गई"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"टाइल हटाई गई"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index f5b9ca5..560938b 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Lijevi rub <xliff:g id="PERCENT">%1$d</xliff:g> posto"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Desni rub <xliff:g id="PERCENT">%1$d</xliff:g> posto"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Spremljeno u aplikaciju <xliff:g id="APP">%1$s</xliff:g> u poslovnom profilu"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Spremljeno u aplikaciju <xliff:g id="APP">%1$s</xliff:g> na privatnom profilu"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Datoteke"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"Aplikacija <xliff:g id="APPNAME">%1$s</xliff:g> otkrila je ovu snimku zaslona."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> i druge otvorene aplikacije otkrile su ovu snimku zaslona."</string>
@@ -274,7 +275,7 @@
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Spremljeno"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"prekini vezu"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktiviraj"</string>
- <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Automatski ponovo uključi sutra"</string>
+ <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Automatski uključi ponovno sutra"</string>
<string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Značajke kao što su brzo dijeljenje i Pronađi moj uređaj koriste Bluetooth"</string>
<string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Bluetooth će se uključiti sutra ujutro"</string>
<string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Zajedničko slušanje"</string>
@@ -457,9 +458,13 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Pokrenuti poslovne aplikacije?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Ponovno pokreni"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Zatvaranje widgeta na zaključanom zaslonu"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Prilagodi widgete"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widgeti na zaključanom zaslonu"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"odaberi widget"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Promjena korisnika"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"padajući izbornik"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Izbrisat će se sve aplikacije i podaci u ovoj sesiji."</string>
@@ -589,9 +594,9 @@
<string name="screen_pinning_negative" msgid="6882816864569211666">"Ne, hvala"</string>
<string name="screen_pinning_start" msgid="7483998671383371313">"Aplikacija je prikvačena"</string>
<string name="screen_pinning_exit" msgid="4553787518387346893">"Aplikacija je otkvačena"</string>
- <string name="stream_voice_call" msgid="7468348170702375660">"Nazovi"</string>
+ <string name="stream_voice_call" msgid="7468348170702375660">"Poziv"</string>
<string name="stream_system" msgid="7663148785370565134">"Sustav"</string>
- <string name="stream_ring" msgid="7550670036738697526">"Zvoni"</string>
+ <string name="stream_ring" msgid="7550670036738697526">"Zvonjenje"</string>
<string name="stream_music" msgid="2188224742361847580">"Mediji"</string>
<string name="stream_alarm" msgid="16058075093011694">"Alarm"</string>
<string name="stream_notification" msgid="7930294049046243939">"Obavijest"</string>
@@ -626,8 +631,10 @@
<string name="volume_panel_collapsed_sliders" msgid="1413383759434791450">"Sažimanje klizača za glasnoću"</string>
<string name="volume_panel_hint_mute" msgid="6962563028495243738">"isključili zvuk za sljedeće: %s"</string>
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"uključili zvuk za sljedeće: %s"</string>
- <string name="media_output_label_title" msgid="872824698593182505">"Reproducira se – <xliff:g id="LABEL">%s</xliff:g>"</string>
- <string name="media_output_title_without_playing" msgid="3825663683169305013">"Zvuk će se reproducirati"</string>
+ <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> se reproducira na"</string>
+ <string name="media_output_title_without_playing" msgid="3825663683169305013">"Zvuk će se reproducirati na"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"Ugađanje korisničkog sučelja sustava"</string>
<string name="status_bar" msgid="4357390266055077437">"Traka statusa"</string>
<string name="demo_mode" msgid="263484519766901593">"Demo način korisničkog sučelja sustava"</string>
@@ -655,10 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satelit, slaba veza"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelit, dobra veza"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, veza je dostupna"</string>
- <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
- <skip />
- <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
- <skip />
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS putem satelita"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Poslovni profil"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Zabava za neke, ali ne za sve"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Ugađanje korisničkog sučelja sustava pruža vam dodatne načine za prilagodbu korisničkog sučelja Androida. Te se eksperimentalne značajke mogu promijeniti, prekinuti ili nestati u budućim izdanjima. Nastavite uz oprez."</string>
@@ -863,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Dodavanje kartice"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Premještanje u prostoriju <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Dodavanje na položaj <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Položaj nije važeći."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Položaj <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Kartica je dodana"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Kartica je uklonjena"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 32dcdfd..2316643 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Bal oldali rész <xliff:g id="PERCENT">%1$d</xliff:g> százaléka"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Jobb oldali rész <xliff:g id="PERCENT">%1$d</xliff:g> százaléka"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Mentve a(z) <xliff:g id="APP">%1$s</xliff:g> alkalmazás munkaprofiljába"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Mentve a(z) <xliff:g id="APP">%1$s</xliff:g> alkalmazás privát profiljában"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Fájlok"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"A(z) <xliff:g id="APPNAME">%1$s</xliff:g> észlelte ezt a képernyőképet."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"A(z) <xliff:g id="APPNAME">%1$s</xliff:g> és más nyitott alkalmazások észlelték ezt a képernyőképet."</string>
@@ -459,6 +460,11 @@
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"A lezárási képernyőn lévő modulok bezárása"</string>
<string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Modulok személyre szabása"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Modulok a lezárási képernyőn"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"modul kiválasztása"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Felhasználóváltás"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"lehúzható menü"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"A munkamenetben található összes alkalmazás és adat törlődni fog."</string>
@@ -627,6 +633,8 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"%s némításának feloldása"</string>
<string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> lejátszása itt:"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"Hang lejátszása itt:"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"Kezelőfelület-hangoló"</string>
<string name="status_bar" msgid="4357390266055077437">"Állapotsor"</string>
<string name="demo_mode" msgid="263484519766901593">"A rendszer kezelőfelületének demómódja"</string>
@@ -654,8 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Műhold, gyenge kapcsolat"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Műhold, jó kapcsolat"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Műhold, van rendelkezésre álló kapcsolat"</string>
- <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"Műholdhoz csatlakozik"</string>
- <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"Nem csatlakozik műholdhoz"</string>
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Műholdas SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Munkaprofil"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Egyeseknek tetszik, másoknak nem"</string>
<string name="tuner_warning" msgid="1861736288458481650">"A Kezelőfelület-hangoló az Android felhasználói felületének szerkesztéséhez és testreszabásához nyújt további megoldásokat. Ezek a kísérleti funkciók változhatnak vagy megsérülhetnek a későbbi kiadásokban, illetve eltűnhetnek azokból. Körültekintően járjon el."</string>
@@ -860,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Mozaik hozzáadása"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Áthelyezés ide: <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Hozzáadás a következő pozícióhoz: <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Érvénytelen pozíció."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"<xliff:g id="POSITION">%1$d</xliff:g>. hely"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Kártya hozzáadva"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Kártya eltávolítva"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index ec090dd..3d70b70 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Ձախ կողմի սահմանագիծը՝ <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Աջ կողմի սահմանագիծը՝ <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Սքրինշոթը պահվեց <xliff:g id="APP">%1$s</xliff:g>-ի աշխատանքային պրոֆիլում"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Սքրինշոթը պահվեց <xliff:g id="APP">%1$s</xliff:g>-ի անձնական պրոֆիլում"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Ֆայլեր"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> հավելվածը հայտնաբերել է այս սքրինշոթը։"</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g>-ն ու բացված այլ հավելվածներ հայտնաբերել են այս սքրինշոթը։"</string>
@@ -457,9 +458,13 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Վերսկսե՞լ աշխ. հավելվածները"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Վերսկսել"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Փակել վիջեթները կողպէկրանին"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Հարմարեցնել վիջեթները"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Վիջեթներ կողպէկրանին"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"ընտրել վիջեթ"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Անջատել օգտվողին"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"իջնող ընտրացանկ"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Այս աշխատաշրջանի բոլոր հավելվածներն ու տվյալները կջնջվեն:"</string>
@@ -627,7 +632,9 @@
<string name="volume_panel_hint_mute" msgid="6962563028495243738">"անջատել ձայնը (%s)"</string>
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"միացնել ձայնը (%s)"</string>
<string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g>. նվագարկվում է"</string>
- <string name="media_output_title_without_playing" msgid="3825663683169305013">"Աուդիոն կնվագարկվի"</string>
+ <string name="media_output_title_without_playing" msgid="3825663683169305013">"Աուդիոն կնվագարկի"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"Համակարգի ՕՄ-ի կարգավորիչ"</string>
<string name="status_bar" msgid="4357390266055077437">"Կարգավիճակի գոտի"</string>
<string name="demo_mode" msgid="263484519766901593">"Համակարգի միջերեսի ցուցադրական ռեժիմ"</string>
@@ -655,10 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Արբանյակային թույլ կապ"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Արբանյակային լավ կապ"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Հասանելի է արբանյակային կապ"</string>
- <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
- <skip />
- <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
- <skip />
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satellite SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Աշխատանքային պրոֆիլ"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Զվարճանք մեկ՝ որոշակի մարդու համար"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Համակարգի ՕՄ-ի կարգավորիչը հնարավորություն է տալիս հարմարեցնել Android-ի օգտատիրոջ միջերեսը: Այս փորձնական գործառույթները կարող են հետագա թողարկումների մեջ փոփոխվել, խափանվել կամ ընդհանրապես չհայտնվել: Եթե շարունակում եք, զգուշացեք:"</string>
@@ -863,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Ավելացնել սալիկ"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Տեղափոխել դիրք <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Ավելացնել դիրք <xliff:g id="POSITION">%1$d</xliff:g>-ում"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Դիրքն անվավեր է։"</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Դիրք <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Սալիկն ավելացվեց"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Սալիկը հեռացվեց"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 2e36d21..bc7bb0f 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Batas kiri <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Batas kanan <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Disimpan di <xliff:g id="APP">%1$s</xliff:g> di profil kerja"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Disimpan di <xliff:g id="APP">%1$s</xliff:g> di profil pribadi"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"File"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> mendeteksi screenshot ini."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> dan aplikasi terbuka lainnya mendeteksi screenshot ini."</string>
@@ -459,6 +460,11 @@
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Tutup widget di layar kunci"</string>
<string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Sesuaikan widget"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widget di layar kunci"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"pilih widget"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Beralih pengguna"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu pulldown"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Semua aplikasi dan data dalam sesi ini akan dihapus."</string>
@@ -627,6 +633,8 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"membunyikan %s"</string>
<string name="media_output_label_title" msgid="872824698593182505">"Memutar <xliff:g id="LABEL">%s</xliff:g> di"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"Audio akan diputar di"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"Penyetel Antarmuka Pengguna Sistem"</string>
<string name="status_bar" msgid="4357390266055077437">"Bilah status"</string>
<string name="demo_mode" msgid="263484519766901593">"Mode demo UI sistem"</string>
@@ -654,8 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satelit, koneksi buruk"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelit, koneksi baik"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, koneksi tersedia"</string>
- <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"Terhubung ke satelit"</string>
- <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"Tidak terhubung ke satelit"</string>
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS via Satelit"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Profil kerja"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Tidak semua orang menganggapnya baik"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Penyetel Antarmuka Pengguna Sistem memberikan cara tambahan untuk mengubah dan menyesuaikan antarmuka pengguna Android. Fitur eksperimental ini dapat berubah, rusak, atau menghilang dalam rilis di masa mendatang. Lanjutkan dengan hati-hati."</string>
@@ -860,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Tambahkan kartu"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Pindahkan ke <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Tambahkan ke posisi <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Posisi tidak valid."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Posisi <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Kartu ditambahkan"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Kartu dihapus"</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 2087907..b30c898 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Vinstri mörk <xliff:g id="PERCENT">%1$d</xliff:g> prósent"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Hægri mörk <xliff:g id="PERCENT">%1$d</xliff:g> prósent"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Vistað á vinnusniði í <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Vistað í <xliff:g id="APP">%1$s</xliff:g> á lokaða prófílnum"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Skrár"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> greindi skjámyndina."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> og önnur opin forrit greindu skjámyndina."</string>
@@ -457,9 +458,13 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Ljúka hléi vinnuforrita?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Ljúka hléi"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Loka græjum á lásskjá"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Sérsníða græjur"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Græjur á lásskjá"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"velja græju"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Skipta um notanda"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"Fellivalmynd"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Öllum forritum og gögnum í þessari lotu verður eytt."</string>
@@ -628,6 +633,8 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"kveikja á hljóði %s"</string>
<string name="media_output_label_title" msgid="872824698593182505">"Í spilun í <xliff:g id="LABEL">%s</xliff:g>"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"Hljóð heldur áfram að spilast"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"Fínstillingar kerfisviðmóts"</string>
<string name="status_bar" msgid="4357390266055077437">"Stöðustika"</string>
<string name="demo_mode" msgid="263484519766901593">"Prufustilling kerfisviðmóts"</string>
@@ -655,10 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Gervihnöttur, léleg tenging"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Gervihnöttur, góð tenging"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Gervihnöttur, tenging tiltæk"</string>
- <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
- <skip />
- <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
- <skip />
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Gervihnattar-SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Vinnusnið"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Þetta er ekki allra"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Fínstillingar kerfisviðmóts gera þér kleift að fínstilla og sérsníða notendaviðmót Android. Þessir tilraunaeiginleikar geta breyst, bilað eða horfið í síðari útgáfum. Gakktu því hægt um gleðinnar dyr."</string>
@@ -863,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Bæta flís við"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Færa í <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Bæta við í stöðu <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Staða ógild."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Staða <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Reit bætt við"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Reitur fjarlægður"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 5931e6a..2102099 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Limite sinistro, <xliff:g id="PERCENT">%1$d</xliff:g> percento"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Limite destro, <xliff:g id="PERCENT">%1$d</xliff:g> percento"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Salvato nell\'app <xliff:g id="APP">%1$s</xliff:g> nel profilo di lavoro"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Salvato nel profilo privato nell\'app <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"File"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> ha rilevato questo screenshot."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> e altre app aperte hanno rilevato questo screenshot."</string>
@@ -457,9 +458,13 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Riattivare le app di lavoro?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Riattiva"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Chiudi widget su schermata di blocco"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Personalizza widget"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widget su schermata di blocco"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"seleziona widget"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Cambio utente"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu a discesa"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Tutte le app e i dati di questa sessione verranno eliminati."</string>
@@ -628,6 +633,8 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"riattivare audio di %s"</string>
<string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> in riproduzione su"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"Audio riprodotto su:"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"Ottimizzatore UI di sistema"</string>
<string name="status_bar" msgid="4357390266055077437">"Barra di stato"</string>
<string name="demo_mode" msgid="263484519766901593">"Modalità demo dell\'interfaccia utente di sistema"</string>
@@ -655,8 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satellitare, connessione debole"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellitare, connessione buona"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellitare, connessione disponibile"</string>
- <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"Connessione satellitare"</string>
- <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"Nessuna connessione satellitare"</string>
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS satellitare"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Profilo di lavoro"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Il divertimento riservato a pochi eletti"</string>
<string name="tuner_warning" msgid="1861736288458481650">"L\'Ottimizzatore UI di sistema mette a disposizione altri metodi per modificare e personalizzare l\'interfaccia utente di Android. Queste funzioni sperimentali potrebbero cambiare, interrompersi o scomparire nelle versioni successive. Procedi con cautela."</string>
@@ -861,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Aggiungi riquadro"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Sposta nella posizione <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Aggiungi alla posizione <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Posizione non valida."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Posizione <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Riquadro aggiunto"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Riquadro rimosso"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 8c2ccbf..5be4172 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"<xliff:g id="PERCENT">%1$d</xliff:g> אחוז מהשוליים השמאליים"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"<xliff:g id="PERCENT">%1$d</xliff:g> אחוז מהשוליים הימניים"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"נשמר באפליקציה <xliff:g id="APP">%1$s</xliff:g> בתוך פרופיל העבודה"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"נשמר באפליקציה <xliff:g id="APP">%1$s</xliff:g> בפרופיל הפרטי"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"קבצים"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"האפליקציה <xliff:g id="APPNAME">%1$s</xliff:g> זיהתה את צילום המסך הזה."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"האפליקציה <xliff:g id="APPNAME">%1$s</xliff:g> ואפליקציות פתוחות נוספות זיהו את צילום המסך הזה."</string>
@@ -457,9 +458,13 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"להפעיל את האפליקציות לעבודה?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"ביטול ההשהיה"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"סגירת ווידג\'טים במסך הנעילה"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"התאמה אישית של ווידג\'טים"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"ווידג\'טים במסך הנעילה"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"צריך לבחור ווידג\'ט"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"החלפת משתמש"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"תפריט במשיכה למטה"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"כל האפליקציות והנתונים בסשן הזה יימחקו."</string>
@@ -628,6 +633,8 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"ביטול ההשתקה של %s"</string>
<string name="media_output_label_title" msgid="872824698593182505">"הפעלה של <xliff:g id="LABEL">%s</xliff:g> במכשיר"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"האודיו יופעל במכשיר"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"System UI Tuner"</string>
<string name="status_bar" msgid="4357390266055077437">"שורת סטטוס"</string>
<string name="demo_mode" msgid="263484519766901593">"מצב הדגמה בממשק המשתמש של המערכת"</string>
@@ -655,8 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"לוויין, חיבור באיכות ירודה"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"לוויין, חיבור באיכות טובה"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"לוויין, יש חיבור זמין"</string>
- <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"יש חיבור ללוויין"</string>
- <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"אין חיבור ללוויין"</string>
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"תקשורת לוויינית למצב חירום"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"פרופיל עבודה"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"מהנה בשביל חלק מהאנשים, אבל לא בשביל כולם"</string>
<string name="tuner_warning" msgid="1861736288458481650">"התכונה System UI Tuner מספקת לך דרכים נוספות להתאים אישית את ממשק המשתמש של Android. התכונות הניסיוניות האלה עשויות להשתנות, לא לעבוד כראוי או להיעלם בגרסאות עתידיות. יש להמשיך בזהירות."</string>
@@ -861,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"הוספת לחצן"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"העברה למיקום <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"הוספה למיקום <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"המיקום לא תקין."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"מיקום <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"הלחצן נוסף"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"הלחצן הוסר"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 54f9c86..62a3a43 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"左の境界線 <xliff:g id="PERCENT">%1$d</xliff:g> パーセント"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"右の境界線 <xliff:g id="PERCENT">%1$d</xliff:g> パーセント"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"仕事用プロファイルで <xliff:g id="APP">%1$s</xliff:g> に保存しました"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"非公開プロフィールの <xliff:g id="APP">%1$s</xliff:g> に保存しました"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"ファイル"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> がこのスクリーンショットを検出しました。"</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> とその他の開いているアプリがこのスクリーンショットを検出しました。"</string>
@@ -459,6 +460,11 @@
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"ロック画面のウィジェットを閉じる"</string>
<string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"ウィジェットのカスタマイズ"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"ロック画面のウィジェット"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"ウィジェットを選択"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ユーザーを切り替える"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"プルダウン メニュー"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"このセッションでのアプリとデータはすべて削除されます。"</string>
@@ -627,6 +633,8 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"%s のミュートを解除"</string>
<string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> の再生先:"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"音声の再生先"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"システムUI調整ツール"</string>
<string name="status_bar" msgid="4357390266055077437">"ステータスバー"</string>
<string name="demo_mode" msgid="263484519766901593">"システム UI デモモード"</string>
@@ -654,8 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"衛生、接続不安定"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"衛生、接続状態良好"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"衛生、接続利用可能"</string>
- <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"衛星に接続済み"</string>
- <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"衛星に未接続"</string>
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"衛星 SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"仕事用プロファイル"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"一部の方のみお楽しみいただける限定公開ツール"</string>
<string name="tuner_warning" msgid="1861736288458481650">"システムUI調整ツールでは、Androidユーザーインターフェースの調整やカスタマイズを行えます。これらの試験運用機能は今後のリリースで変更となったり、中止となったり、削除されたりする可能性がありますのでご注意ください。"</string>
@@ -860,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"タイルを追加"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g> に移動"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"ポジション <xliff:g id="POSITION">%1$d</xliff:g> に追加"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"位置が無効です。"</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"位置: <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"タイルを追加しました"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"タイルを削除しました"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index 9c814b4..2a4f5d6 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"მარცხენა ზღვარი: <xliff:g id="PERCENT">%1$d</xliff:g> პროცენტი"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"მარჯვენა ზღვარი: <xliff:g id="PERCENT">%1$d</xliff:g> პროცენტი"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"შენახულია <xliff:g id="APP">%1$s</xliff:g>-ში სამსახურის პროფილში"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"შენახულია <xliff:g id="APP">%1$s</xliff:g>-ში, პირად პროფილში"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"ფაილები"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g>-მა აღმოაჩინა ეკრანის ეს ანაბეჭდი"</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g>-მა და სხვა გახსნილმა აპებმა აღმოაჩინეს ეკრანის ეს ანაბეჭდი."</string>
@@ -459,6 +460,11 @@
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"ჩაკეტილ ეკრანზე ვიჯეტების დახურვა"</string>
<string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"ვიჯეტების მორგება"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"ვიჯეტები ჩაკეტილ ეკრანზე"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"ვიჯეტის არჩევა"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"მომხმარებლის გადართვა"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ჩამოშლადი მენიუ"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ამ სესიის ყველა აპი და მონაცემი წაიშლება."</string>
@@ -627,6 +633,7 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"%s-ის დადუმების მოხსნა"</string>
<string name="media_output_label_title" msgid="872824698593182505">"უკრავს <xliff:g id="LABEL">%s</xliff:g>:"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"აუდიო დაიკვრება"</string>
+ <string name="media_output_title_ongoing_call" msgid="208426888064112006">"მიმდინარეობს ზარი"</string>
<string name="system_ui_tuner" msgid="1471348823289954729">"სისტემის UI ტუნერი"</string>
<string name="status_bar" msgid="4357390266055077437">"სტატუსის ზოლი"</string>
<string name="demo_mode" msgid="263484519766901593">"სისტემის UI-ს დემო-რეჟიმი"</string>
@@ -654,10 +661,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"სუსტი სატელიტური კავშირი"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"კარგი სატელიტური კავშირი"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ხელმისაწვდომია სატელიტური კავშირი"</string>
- <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
- <skip />
- <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
- <skip />
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"სატელიტური SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"სამსახურის პროფილი"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"ზოგისთვის გასართობია, მაგრამ არა ყველასთვის"</string>
<string name="tuner_warning" msgid="1861736288458481650">"სისტემის UI ტუნერი გაძლევთ დამატებით გზებს Android-ის სამომხმარებლო ინტერფეისის პარამეტრების დაყენებისთვის. ეს ექსპერიმენტული მახასიათებლები შეიძლება შეიცვალოს, შეწყდეს ან გაქრეს მომავალ ვერსიებში. სიფრთხილით გააგრძელეთ."</string>
@@ -862,6 +866,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"მოზაიკის დამატება"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"გადატანა <xliff:g id="POSITION">%1$d</xliff:g>-ზე"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"დამატება პოზიციაზე <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"პოზიცია არასწორია."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"პოზიცია <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"მოზაიკის ფილა დაემატა"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"მოზაიკის ფილა ამოიშალა"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 5fe1a2c..398677e 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Сол жақ шектік сызық: <xliff:g id="PERCENT">%1$d</xliff:g> пайыз"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Оң жақ шектік сызық: <xliff:g id="PERCENT">%1$d</xliff:g> пайыз"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Жұмыс профиліндегі <xliff:g id="APP">%1$s</xliff:g> қолданбасында сақталған."</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Жеке профильдегі <xliff:g id="APP">%1$s</xliff:g> қолданбасында сақталды."</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Files"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> қолданбасы осы скриншотты анықтады."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> және басқа да ашық қолданбалар осы скриншотты анықтады."</string>
@@ -459,6 +460,11 @@
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Құлыптаулы экранда виджеттерді жабу"</string>
<string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Виджеттерді бейімдеу"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Құлыптаулы экрандағы виджеттер"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"виджет таңдау"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Пайдаланушыны ауыстыру"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ашылмалы мәзір"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Осы сеанстағы барлық қолданба мен дерек жойылады."</string>
@@ -627,6 +633,8 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"%s дыбысын қосу"</string>
<string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> ойнатылатын құрылғы:"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"Аудио ойнатылатын құрылғы:"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"Жүйелік пайдаланушылық интерфейс тюнері"</string>
<string name="status_bar" msgid="4357390266055077437">"Күйін көрсету жолағы"</string>
<string name="demo_mode" msgid="263484519766901593">"Жүйе интерфейсінің демо режимі"</string>
@@ -654,8 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Жерсерік, байланыс нашар."</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Жерсерік, байланыс жақсы."</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Жерсерік, байланыс бар."</string>
- <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"Жерсерік сигналына қосылғансыз."</string>
- <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"Жерсерік сигналына қосылмағансыз."</string>
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satellite SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Жұмыс профилі"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Кейбіреулерге қызық, бірақ барлығына емес"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Жүйелік пайдаланушылық интерфейс тюнері Android пайдаланушылық интерфейсін реттеудің қосымша жолдарын береді. Бұл эксперименттік мүмкіндіктер болашақ шығарылымдарда өзгеруі, бұзылуы немесе жоғалуы мүмкін. Сақтықпен жалғастырыңыз."</string>
@@ -860,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Бөлшек қосу"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g> орнына жылжыту"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g> орнына қосу"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Орын жарамсыз."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"<xliff:g id="POSITION">%1$d</xliff:g> орны"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Бөлшек қосылды."</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Бөлшек өшірілді."</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 91292a1..e32da00 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"បន្ទាត់បែងចែកខាងឆ្វេង <xliff:g id="PERCENT">%1$d</xliff:g> ភាគរយ"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"បន្ទាត់បែងចែកខាងស្ដាំ <xliff:g id="PERCENT">%1$d</xliff:g> ភាគរយ"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"បានរក្សាទុកនៅក្នុង <xliff:g id="APP">%1$s</xliff:g> ក្នុងកម្រងព័ត៌មានការងារ"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"បានរក្សាទុកនៅក្នុង <xliff:g id="APP">%1$s</xliff:g> ក្នុងកម្រងព័ត៌មានឯកជន"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"ឯកសារ"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> បានរកឃើញរូបថតអេក្រង់នេះ។"</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> និងកម្មវិធីដែលបើកផ្សេងទៀតបានរកឃើញរូបថតអេក្រង់នេះ។"</string>
@@ -459,6 +460,11 @@
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"បិទធាតុក្រាហ្វិកនៅលើអេក្រង់ចាក់សោ"</string>
<string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"ប្ដូរធាតុក្រាហ្វិកតាមបំណង"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"ធាតុក្រាហ្វិកនៅលើអេក្រង់ចាក់សោ"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"ជ្រើសរើសធាតុក្រាហ្វិក"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ប្ដូរអ្នកប្រើ"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ម៉ឺនុយទាញចុះ"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"កម្មវិធី និងទិន្នន័យទាំងអស់ក្នុងវគ្គនេះនឹងត្រូវលុប។"</string>
@@ -627,6 +633,8 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"បើកសំឡេង %s"</string>
<string name="media_output_label_title" msgid="872824698593182505">"កំពុងចាក់ <xliff:g id="LABEL">%s</xliff:g> នៅលើ"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"សំឡេងនឹងលេងនៅលើ"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"កម្មវិធីសម្រួល UI ប្រព័ន្ធ"</string>
<string name="status_bar" msgid="4357390266055077437">"របារស្ថានភាព"</string>
<string name="demo_mode" msgid="263484519766901593">"មុខងារសាកល្បង UI ប្រព័ន្ធ"</string>
@@ -654,8 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"ផ្កាយរណប ការតភ្ជាប់ខ្សោយ"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"ផ្កាយរណប មានការតភ្ជាប់ល្អ"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ផ្កាយរណប អាចតភ្ជាប់បាន"</string>
- <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"បានភ្ជាប់ទៅផ្កាយរណប"</string>
- <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"មិនបានភ្ជាប់ទៅផ្កាយរណប"</string>
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"ការប្រកាសអាសន្នតាមផ្កាយរណប"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"កម្រងព័ត៌មានការងារ"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"ល្អសម្រាប់អ្នកប្រើមួយចំនួន តែមិនសម្រាប់គ្រប់គ្នាទេ"</string>
<string name="tuner_warning" msgid="1861736288458481650">"កម្មវិធីសម្រួល UI ប្រព័ន្ធផ្តល់ជូនអ្នកនូវមធ្យោបាយបន្ថែមទៀតដើម្បីកែសម្រួល និងប្តូរចំណុចប្រទាក់អ្នកប្រើ Android តាមបំណង។ លក្ខណៈពិសេសសាកល្បងនេះអាចនឹងផ្លាស់ប្តូរ បំបែក ឬបាត់បង់បន្ទាប់ពីការចេញផ្សាយនាពេលអនាគត។ សូមបន្តដោយប្រុងប្រយ័ត្ន។"</string>
@@ -860,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"បញ្ចូលប្រអប់"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"ផ្លាស់ទីទៅ <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"បញ្ចូលទៅទីតាំងទី <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"ទីតាំងគ្មានសុពលភាព។"</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"ទីតាំងទី <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"បានបញ្ចូលប្រអប់"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"បានផ្លាស់ទីប្រអប់"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 0d4449a..e217f8e 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"ಎಡಭಾಗದ ಬೌಂಡರಿ ಶೇಕಡಾ <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"ಬಲಭಾಗದ ಬೌಂಡರಿ ಶೇಕಡಾ <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"ಕೆಲಸದ ಪ್ರೊಫೈಲ್ನಲ್ಲಿನ <xliff:g id="APP">%1$s</xliff:g> ನಲ್ಲಿ ಸೇವ್ ಮಾಡಲಾಗಿದೆ"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"ಖಾಸಗಿ ಪ್ರೊಫೈಲ್ನಲ್ಲಿನ <xliff:g id="APP">%1$s</xliff:g> ನಲ್ಲಿ ಸೇವ್ ಮಾಡಲಾಗಿದೆ"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"ಫೈಲ್ಗಳು"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"ಈ ಸ್ಕ್ರೀನ್ಶಾಟ್ ಅನ್ನು <xliff:g id="APPNAME">%1$s</xliff:g> ಪತ್ತೆಹಚ್ಚಿದೆ."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> ಹಾಗೂ ತೆರೆದಿರುವ ಇತರ ಆ್ಯಪ್ಗಳು ಈ ಸ್ಕ್ರೀನ್ಶಾಟ್ ಅನ್ನು ಪತ್ತೆಹಚ್ಚಿವೆ."</string>
@@ -459,6 +460,11 @@
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"ಲಾಕ್ ಸ್ಕ್ರೀನ್ನಲ್ಲಿ ವಿಜೆಟ್ಗಳನ್ನು ಮುಚ್ಚಿರಿ"</string>
<string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"ವಿಜೆಟ್ಗಳನ್ನು ಕಸ್ಟಮೈಸ್ ಮಾಡಿ"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"ಲಾಕ್ ಸ್ಕ್ರೀನ್ನಲ್ಲಿ ವಿಜೆಟ್ಗಳು"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"ವಿಜೆಟ್ ಅನ್ನು ಆಯ್ಕೆ ಮಾಡಿ"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ಬಳಕೆದಾರರನ್ನು ಬದಲಿಸಿ"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ಪುಲ್ಡೌನ್ ಮೆನು"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ಈ ಸೆಶನ್ನಲ್ಲಿನ ಎಲ್ಲಾ ಆ್ಯಪ್ಗಳು ಮತ್ತು ಡೇಟಾವನ್ನು ಅಳಿಸಲಾಗುತ್ತದೆ."</string>
@@ -627,6 +633,7 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"%s ಅನ್ಮ್ಯೂಟ್ ಮಾಡಿ"</string>
<string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> ನಲ್ಲಿ ಪ್ಲೇ ಆಗು..."</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"ಇದರಲ್ಲಿ ಪ್ಲೇ ಆಗುತ್ತದೆ"</string>
+ <string name="media_output_title_ongoing_call" msgid="208426888064112006">"ಕರೆ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
<string name="system_ui_tuner" msgid="1471348823289954729">"ಸಿಸ್ಟಂ UI ಟ್ಯೂನರ್"</string>
<string name="status_bar" msgid="4357390266055077437">"ಸ್ಥಿತಿ ಪಟ್ಟಿ"</string>
<string name="demo_mode" msgid="263484519766901593">"ಸಿಸ್ಟಂ UI ಡೆಮೋ ಮೋಡ್"</string>
@@ -654,8 +661,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"ಸ್ಯಾಟಲೈಟ್, ಕನೆಕ್ಷನ್ ಕಳಪೆಯಾಗಿದೆ"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"ಸ್ಯಾಟಲೈಟ್, ಕನೆಕ್ಷನ್ ಉತ್ತಮವಾಗಿದೆ"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ಸ್ಯಾಟಲೈಟ್, ಕನೆಕ್ಷನ್ ಲಭ್ಯವಿದೆ"</string>
- <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"ಸ್ಯಾಟಲೈಟ್ಗೆ ಕನೆಕ್ಟ್ ಮಾಡಲಾಗಿದೆ"</string>
- <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"ಸ್ಯಾಟಲೈಟ್ಗೆ ಕನೆಕ್ಟ್ ಮಾಡಿಲ್ಲ"</string>
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"ಸ್ಯಾಟಲೈಟ್ SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"ಕೆಲಸದ ಪ್ರೊಫೈಲ್"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"ಕೆಲವರಿಗೆ ಮೋಜು ಆಗಿದೆ ಎಲ್ಲರಿಗೆ ಇಲ್ಲ"</string>
<string name="tuner_warning" msgid="1861736288458481650">"ಸಿಸ್ಟಂ UI ಟ್ಯೂನರ್ ನಿಮಗೆ Android ಬಳಕೆದಾರ ಅಂತರಸಂಪರ್ಕವನ್ನು ಸರಿಪಡಿಸಲು ಮತ್ತು ಕಸ್ಟಮೈಸ್ ಮಾಡಲು ಹೆಚ್ಚುವರಿ ಮಾರ್ಗಗಳನ್ನು ನೀಡುತ್ತದೆ. ಈ ಪ್ರಾಯೋಗಿಕ ವೈಶಿಷ್ಟ್ಯಗಳು ಭವಿಷ್ಯದ ಬಿಡುಗಡೆಗಳಲ್ಲಿ ಬದಲಾಗಬಹುದು, ವಿರಾಮವಾಗಬಹುದು ಅಥವಾ ಕಾಣಿಸಿಕೊಳ್ಳದಿರಬಹುದು. ಎಚ್ಚರಿಕೆಯಿಂದ ಮುಂದುವರಿಯಿರಿ."</string>
@@ -860,6 +866,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"ಟೈಲ್ ಸೇರಿಸಿ"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"ಇಲ್ಲಿಗೆ ಸರಿಸಿ <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g> ಸ್ಥಾನಕ್ಕೆ ಸೇರಿಸಿ"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"ಸ್ಥಾನವು ಅಮಾನ್ಯವಾಗಿದೆ."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"ಸ್ಥಾನ <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"ಟೈಲ್ ಸೇರಿಸಲಾಗಿದೆ"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"ಟೈಲ್ ತೆಗೆದುಹಾಕಲಾಗಿದೆ"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 2d9058e..3ef3dc8 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"왼쪽 가장자리 <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"오른쪽 가장자리 <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"직장 프로필의 <xliff:g id="APP">%1$s</xliff:g>에 저장되었습니다."</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"<xliff:g id="APP">%1$s</xliff:g>의 비공개 프로필에 저장됨"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"파일"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g>에서 이 스크린샷을 감지했습니다."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> 및 기타 공개 앱에서 이 스크린샷을 감지했습니다."</string>
@@ -457,9 +458,13 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"직장 앱 일시중지를 해제하시겠습니까?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"일시중지 해제"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"잠금 화면에서 위젯 닫기"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"위젯 맞춤설정"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"잠금 화면의 위젯"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"위젯 선택"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"사용자 전환"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"풀다운 메뉴"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"이 세션에 있는 모든 앱과 데이터가 삭제됩니다."</string>
@@ -628,6 +633,7 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"%s 음소거 해제"</string>
<string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> 재생 위치:"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"오디오 재생 위치:"</string>
+ <string name="media_output_title_ongoing_call" msgid="208426888064112006">"전화 거는 중"</string>
<string name="system_ui_tuner" msgid="1471348823289954729">"시스템 UI 튜너"</string>
<string name="status_bar" msgid="4357390266055077437">"상태 표시줄"</string>
<string name="demo_mode" msgid="263484519766901593">"시스템 UI 데모 모드"</string>
@@ -655,10 +661,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"위성, 연결 상태 나쁨"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"위성, 연결 상태 양호"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"위성, 연결 가능"</string>
- <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
- <skip />
- <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
- <skip />
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"위성 긴급 SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"직장 프로필"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"마음에 들지 않을 수도 있음"</string>
<string name="tuner_warning" msgid="1861736288458481650">"시스템 UI 튜너를 사용하면 Android 사용자 인터페이스를 변경 및 맞춤설정할 수 있습니다. 이러한 실험실 기능은 향후 출시 버전에서는 변경되거나 다운되거나 사라질 수 있습니다. 신중하게 진행하시기 바랍니다."</string>
@@ -863,6 +866,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"타일 추가"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g> 위치로 이동"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g> 위치에 추가"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"위치가 잘못되었습니다."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"<xliff:g id="POSITION">%1$d</xliff:g> 위치"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"타일 추가됨"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"타일 삭제됨"</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 1767c076..a75d0d5 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Сол жагы <xliff:g id="PERCENT">%1$d</xliff:g> пайызга"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Оң жагы <xliff:g id="PERCENT">%1$d</xliff:g> пайызга"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Жумуш профилиндеги <xliff:g id="APP">%1$s</xliff:g> колдонмосуна сакталды"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Жеке профилдеги <xliff:g id="APP">%1$s</xliff:g> колдонмосуна сакталды"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Files"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> ушул скриншотту аныктады."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> жана ачылып турган башка колдонмолор ушул скриншотту аныктады."</string>
@@ -457,9 +458,13 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Жумуш колдонмолорун иштетесизби?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Иштетүү"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Виджеттерди кулпуланган экранда жабуу"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Виджеттерди ыңгайлаштыруу"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Кулпуланган экрандагы виджеттер"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"виджет тандоо"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Колдонуучуну которуу"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ылдый түшүүчү меню"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Бул сеанстагы бардык колдонмолор жана аларга байланыштуу нерселер өчүрүлөт."</string>
@@ -628,6 +633,7 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"%s үнүн чыгаруу"</string>
<string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> аркылуу ойнотулууда"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"Аудио кайсы жерде ойнотулат:"</string>
+ <string name="media_output_title_ongoing_call" msgid="208426888064112006">"Чалууда"</string>
<string name="system_ui_tuner" msgid="1471348823289954729">"System UI Tuner"</string>
<string name="status_bar" msgid="4357390266055077437">"Абал тилкеси"</string>
<string name="demo_mode" msgid="263484519766901593">"Системанын интерфейсинин демо режими"</string>
@@ -655,10 +661,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Спутник, байланыш начар"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Спутник, байланыш жакшы"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Спутник, байланыш бар"</string>
- <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
- <skip />
- <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
- <skip />
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Спутник SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Жумуш профили"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Баарына эле жага бербейт"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner Android колдонуучу интерфейсин жөнгө салып жана ыңгайлаштыруунун кошумча ыкмаларын сунуштайт. Бул сынамык функциялар кийинки чыгарылыштарда өзгөрүлүп, бузулуп же жоголуп кетиши мүмкүн. Абайлап колдонуңуз."</string>
@@ -863,6 +866,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Ыкчам баскыч кошуу"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Төмөнкүгө жылдыруу: <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g>-позицияга кошуу"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Абал жараксыз."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"<xliff:g id="POSITION">%1$d</xliff:g>-позиция"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Карта кошулду"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Карта өчүрүлдү"</string>
diff --git a/packages/SystemUI/res/values-land/styles.xml b/packages/SystemUI/res/values-land/styles.xml
index 2769bea..73812c9 100644
--- a/packages/SystemUI/res/values-land/styles.xml
+++ b/packages/SystemUI/res/values-land/styles.xml
@@ -39,7 +39,7 @@
</style>
<style name="TextAppearance.AuthNonBioCredential.Title">
- <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
+ <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
<item name="android:layout_marginTop">6dp</item>
<item name="android:textSize">36dp</item>
<item name="android:focusable">true</item>
@@ -47,14 +47,14 @@
</style>
<style name="TextAppearance.AuthNonBioCredential.Subtitle">
- <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
+ <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
<item name="android:layout_marginTop">6dp</item>
<item name="android:textSize">18sp</item>
<item name="android:textColor">?androidprv:attr/materialColorOnSurface</item>
</style>
<style name="TextAppearance.AuthNonBioCredential.Description">
- <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
+ <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
<item name="android:layout_marginTop">6dp</item>
<item name="android:textSize">18sp</item>
<item name="android:textColor">?androidprv:attr/materialColorOnSurface</item>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index dc596bf..eca041e 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"ຂອບເຂດທາງຊ້າຍ <xliff:g id="PERCENT">%1$d</xliff:g> ເປີເຊັນ"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"ຂອບເຂດທາງຂວາ <xliff:g id="PERCENT">%1$d</xliff:g> ເປີເຊັນ"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"ບັນທຶກໃນ <xliff:g id="APP">%1$s</xliff:g> ໃນໂປຣໄຟລ໌ບ່ອນເຮັດວຽກແລ້ວ"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"ບັນທຶກໄວ້ໃນ <xliff:g id="APP">%1$s</xliff:g> ໃນໂປຣໄຟລ໌ສ່ວນຕົວແລ້ວ"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"ໄຟລ໌"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> ກວດພົບຮູບໜ້າຈໍນີ້."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> ແລະ ແອັບອື່ນໆທີ່ເປີດຢູ່ກວດພົບຮູບໜ້າຈໍນີ້."</string>
@@ -459,6 +460,11 @@
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"ປິດວິດເຈັດຢູ່ໜ້າຈໍລັອກ"</string>
<string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"ປັບແຕ່ງວິດເຈັດ"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"ວິດເຈັດຢູ່ໜ້າຈໍລັອກ"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"ເລືອກວິດເຈັດ"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ສະຫຼັບຜູ້ໃຊ້"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ເມນູແບບດຶງລົງ"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ແອັບຯແລະຂໍ້ມູນທັງໝົດໃນເຊດຊັນນີ້ຈະຖືກລຶບອອກ."</string>
@@ -627,6 +633,7 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"ເຊົາປິດສຽງ %s"</string>
<string name="media_output_label_title" msgid="872824698593182505">"ກຳລັງຫຼິ້ນ <xliff:g id="LABEL">%s</xliff:g> ໃນ"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"ສຽງຈະຫຼິ້ນຕໍ່ໄປ"</string>
+ <string name="media_output_title_ongoing_call" msgid="208426888064112006">"ກຳລັງໂທ"</string>
<string name="system_ui_tuner" msgid="1471348823289954729">"System UI Tuner"</string>
<string name="status_bar" msgid="4357390266055077437">"ແຖບສະຖານະ"</string>
<string name="demo_mode" msgid="263484519766901593">"ໂໝດເດໂມສ່ວນຕິດຕໍ່ຜູ້ໃຊ້ລະບົບ"</string>
@@ -654,8 +661,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"ດາວທຽມ, ການເຊື່ອມຕໍ່ບໍ່ດີ"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"ດາວທຽມ, ການເຊື່ອມຕໍ່ດີ"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ດາວທຽມ, ການເຊື່ອມຕໍ່ທີ່ພ້ອມນຳໃຊ້"</string>
- <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"ເຊື່ອມຕໍ່ຫາດາວທຽມແລ້ວ"</string>
- <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"ບໍ່ໄດ້ເຊື່ອມຕໍ່ຫາດາວທຽມ"</string>
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS ດາວທຽມ"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"ໂປຣໄຟລ໌ບ່ອນເຮັດວຽກ"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"ມ່ວນຊື່ນສຳລັບບາງຄົນ ແຕ່ບໍ່ແມ່ນສຳລັບທຸກຄົນ"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner ໃຫ້ທ່ານມີວິທີພິເສດຕື່ມອີກໃນການປັບປ່ຽນ ແລະຕົບແຕ່ງສ່ວນຕໍ່ປະສານຜູ້ໃຊ້ຂອງ Android. ຄຸນສົມບັດທົດລອງໃຊ້ເຫຼົ່ານີ້ອາດຈະປ່ຽນແປງ, ຢຸດເຊົາ ຫຼືຫາຍໄປໃນການວາງຈຳໜ່າຍໃນອະນາຄົດ. ຈົ່ງດຳເນີນຕໍ່ດ້ວຍຄວາມລະມັດລະວັງ."</string>
@@ -860,6 +866,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"ເພີ່ມແຜ່ນ"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"ຍ້າຍໄປ <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"ເພີ່ມໃສ່ຕຳແໜ່ງ <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"ຕຳແໜ່ງບໍ່ຖືກຕ້ອງ."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"ຕຳແໜ່ງ <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"ເພີ່ມແຜ່ນແລ້ວ"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"ລຶບແຜ່ນແລ້ວ"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index e6703ce..fa5790c 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Kairioji riba – <xliff:g id="PERCENT">%1$d</xliff:g> proc."</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Dešinioji riba – <xliff:g id="PERCENT">%1$d</xliff:g> proc."</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Išsaugota programoje „<xliff:g id="APP">%1$s</xliff:g>“ darbo profilyje"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Išsaugota „<xliff:g id="APP">%1$s</xliff:g>“ privačiame profilyje"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Failai"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"„<xliff:g id="APPNAME">%1$s</xliff:g>“ aptiko šią ekrano kopiją."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"„<xliff:g id="APPNAME">%1$s</xliff:g>“ ir kitos atidarytos programos aptiko šią ekrano kopiją."</string>
@@ -459,6 +460,11 @@
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Uždaryti valdiklius užrakinimo ekrane"</string>
<string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Tinkinti valdiklius"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Valdikliai užrakinimo ekrane"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"pasirinkite valdiklį"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Perjungti naudotoją"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"išplečiamasis meniu"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Bus ištrintos visos šios sesijos programos ir duomenys."</string>
@@ -627,6 +633,7 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"įjungti garsą %s"</string>
<string name="media_output_label_title" msgid="872824698593182505">"Leidžiama „<xliff:g id="LABEL">%s</xliff:g>“"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"Garsas bus leidžiamas"</string>
+ <string name="media_output_title_ongoing_call" msgid="208426888064112006">"Skambinama"</string>
<string name="system_ui_tuner" msgid="1471348823289954729">"Sistemos naudotojo sąsajos derinimo priemonė"</string>
<string name="status_bar" msgid="4357390266055077437">"Būsenos juosta"</string>
<string name="demo_mode" msgid="263484519766901593">"Sistemos NS demonstracinis režimas"</string>
@@ -654,8 +661,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Palydovas, prastas ryšys"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Palydovas, geras ryšys"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Palydovas, pasiekiamas ryšys"</string>
- <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"Prisijungta prie palydovo"</string>
- <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"Neprisijungta prie palydovo"</string>
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Prisijungimas prie palydovo kritiniu atveju"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Darbo profilis"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Smagu, bet ne visada"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Sistemos naudotojo sąsajos derinimo priemonė suteikia papildomų galimybių pagerinti ir tinkinti „Android“ naudotojo sąsają. Šios eksperimentinės funkcijos gali pasikeisti, nutrūkti ar išnykti iš būsimų laidų. Tęskite atsargiai."</string>
@@ -860,6 +866,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Pridėti išklotinės elementą"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Perkelkite į <xliff:g id="POSITION">%1$d</xliff:g> poziciją"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Pridėkite <xliff:g id="POSITION">%1$d</xliff:g> pozicijoje"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Padėtis netinkama."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"<xliff:g id="POSITION">%1$d</xliff:g> pozicija"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Išklotinė pridėta"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Išklotinė pašalinta"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 9a2a292..9e01526 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Kreisā mala: <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Labā mala: <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Saglabāts lietotnē <xliff:g id="APP">%1$s</xliff:g> darba profilā"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Saglabāts privātā profilā lietotnē <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Faili"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> konstatēja, ka tika veikts ekrānuzņēmums."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> un citas atvērtas lietotnes konstatēja, ka tika veikts ekrānuzņēmums."</string>
@@ -457,9 +458,13 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Vai aktivizēt darba lietotnes?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Aktivizēt"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Aizvērt logrīkus bloķēšanas ekrānā"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Pielāgot logrīkus"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Logrīki bloķēšanas ekrānā"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"atlasīt logrīku"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Mainīt lietotāju"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"novelkamā izvēlne"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Tiks dzēstas visas šīs sesijas lietotnes un dati."</string>
@@ -628,6 +633,8 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"ieslēgt skaņu straumei %s"</string>
<string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> — atskaņošana šeit:"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"Audio tiks atskaņots šeit:"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"Sistēmas saskarnes regulators"</string>
<string name="status_bar" msgid="4357390266055077437">"Statusa josla"</string>
<string name="demo_mode" msgid="263484519766901593">"Sistēmas lietotāja saskarnes demonstrācijas režīms"</string>
@@ -655,10 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satelīts, vājš savienojums"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelīts, labs savienojums"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelīts, ir pieejams savienojums"</string>
- <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
- <skip />
- <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
- <skip />
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satelīta SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Darba profils"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Jautri dažiem, bet ne visiem"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Sistēmas saskarnes regulators sniedz papildu veidus, kā mainīt un pielāgot Android lietotāja saskarni. Nākamajās versijās šīs eksperimentālās funkcijas var tikt mainītas, bojātas vai to darbība var tikt pārtraukta. Turpinot esiet uzmanīgs."</string>
@@ -863,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Pievienot elementu"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Pārvietot uz pozīciju numur <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Pievienot elementu pozīcijā numur <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Nederīga pozīcija."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Pozīcija numur <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Elements ir pievienots"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Elements ir noņemts"</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 552e5e5..d1e26e5 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Лева граница <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Десна граница <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Зачувано во <xliff:g id="APP">%1$s</xliff:g> во работниот профил"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Зачувано во <xliff:g id="APP">%1$s</xliff:g> во приватниот профил"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Датотеки"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> ја откри оваа слика од екранот."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> и други отворени апликации ја открија оваа слика од екранот."</string>
@@ -457,9 +458,13 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Да се актив. работните аплик.?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Прекини ја паузата"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Затворете ги виџетите на заклучениот екран"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Приспособете ги виџетите"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Виџети на заклучен екран"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"изберете виџет"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Промени го корисникот"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"паѓачко мени"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Сите апликации и податоци во сесијава ќе се избришат."</string>
@@ -628,6 +633,8 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"вклучување звук на %s"</string>
<string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g>: пуштено на"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"Аудиото ќе се пушти на"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"Адаптер на УИ на системот"</string>
<string name="status_bar" msgid="4357390266055077437">"Статусна лента"</string>
<string name="demo_mode" msgid="263484519766901593">"Демо-режим на кориснички интерфејс на систем"</string>
@@ -655,10 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Слаба сателитска врска"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Добра сателитска врска"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Достапна е сателитска врска"</string>
- <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
- <skip />
- <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
- <skip />
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Сателитски SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Работен профил"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Забава за некои, но не за сите"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Адаптерот на УИ на системот ви дава дополнителни начини за дотерување и приспособување на корисничкиот интерфејс на Android. Овие експериментални функции можеби ќе се изменат, расипат или ќе исчезнат во следните изданија. Продолжете со претпазливост."</string>
@@ -863,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Додавање плочка"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Преместување на <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Додавање на позиција <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Позицијата е погрешна."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Позиција <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Додадена е плочка"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Отстранета е плочка"</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index c3fdf84..79be0f1 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"ഇടത് വശത്തെ അതിർത്തി <xliff:g id="PERCENT">%1$d</xliff:g> ശതമാനം"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"വലത് വശത്തെ അതിർത്തി <xliff:g id="PERCENT">%1$d</xliff:g> ശതമാനം"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"ഔദ്യോഗിക പ്രൊഫൈലിൽ <xliff:g id="APP">%1$s</xliff:g> ആപ്പിൽ സംരക്ഷിച്ചു"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"സ്വകാര്യ പ്രൊഫൈലിൽ <xliff:g id="APP">%1$s</xliff:g> ആപ്പിൽ സംരക്ഷിച്ചു"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"ഫയലുകൾ"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> ഈ സ്ക്രീൻഷോട്ട് തിരിച്ചറിഞ്ഞു."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> എന്ന ആപ്പും തുറന്നിരിക്കുന്ന മറ്റ് ആപ്പും ഈ സ്ക്രീൻഷോട്ട് തിരിച്ചറിഞ്ഞു."</string>
@@ -459,6 +460,11 @@
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"ലോക്ക് സ്ക്രീനിൽ വിജറ്റുകൾ അടയ്ക്കുക"</string>
<string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"വിജറ്റുകൾ ഇഷ്ടാനുസൃതമാക്കുക"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"ലോക്ക് സ്ക്രീനിൽ വിജറ്റുകൾ"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"വിജറ്റ് തിരഞ്ഞെടുക്കുക"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ഉപയോക്താവ് മാറുക"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"പുൾഡൗൺ മെനു"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ഈ സെഷനിലെ എല്ലാ ആപ്പുകളും ഡാറ്റയും ഇല്ലാതാക്കും."</string>
@@ -627,6 +633,7 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"%s അൺമ്യൂട്ട് ചെയ്യുക"</string>
<string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> എന്നതിൽ പ്ലേ ചെയ്യുന്നു"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"ഓഡിയോ പ്ലേ ചെയ്യും"</string>
+ <string name="media_output_title_ongoing_call" msgid="208426888064112006">"കോൾ പുരോഗമിക്കുന്നു"</string>
<string name="system_ui_tuner" msgid="1471348823289954729">"സിസ്റ്റം UI ട്യൂണർ"</string>
<string name="status_bar" msgid="4357390266055077437">"സ്റ്റാറ്റസ് ബാർ"</string>
<string name="demo_mode" msgid="263484519766901593">"സിസ്റ്റം UI ഡെമോ മോഡ്"</string>
@@ -654,8 +661,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"സാറ്റലൈറ്റ്, മോശം കണക്ഷൻ"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"സാറ്റലൈറ്റ്, മികച്ച കണക്ഷൻ"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"സാറ്റലൈറ്റ്, കണക്ഷൻ ലഭ്യമാണ്"</string>
- <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"സാറ്റലൈറ്റുമായി കണക്റ്റ് ചെയ്തിരിക്കുന്നു"</string>
- <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"സാറ്റലൈറ്റുമായി കണക്റ്റ് ചെയ്തിട്ടില്ല"</string>
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"സാറ്റലൈറ്റ് SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"ഔദ്യോഗിക പ്രൊഫൈൽ"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"ചിലർക്ക് വിനോദം, എന്നാൽ എല്ലാവർക്കുമില്ല"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Android ഉപയോക്തൃ ഇന്റർഫേസ് ആവശ്യമുള്ള രീതിയിൽ മാറ്റുന്നതിനും ഇഷ്ടാനുസൃതമാക്കുന്നതിനും സിസ്റ്റം UI ട്യൂണർ നിങ്ങൾക്ക് അധിക വഴികൾ നൽകുന്നു. ഭാവി റിലീസുകളിൽ ഈ പരീക്ഷണാത്മക ഫീച്ചറുകൾ മാറ്റുകയോ നിർത്തുകയോ അപ്രത്യക്ഷമാവുകയോ ചെയ്തേക്കാം. ശ്രദ്ധയോടെ മുന്നോട്ടുപോകുക."</string>
@@ -860,6 +866,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"ടൈൽ ചേർക്കുക"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g> എന്നതിലേക്ക് നീക്കുക"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g> എന്ന സ്ഥാനത്തേക്ക് ചേർക്കുക"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"സ്ഥാനം അസാധുവാണ്."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"സ്ഥാനം <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"ടൈൽ ചേർത്തു"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"ടൈൽ നീക്കം ചെയ്തു"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 428ceff..93304d6 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Зүүн талын хязгаар <xliff:g id="PERCENT">%1$d</xliff:g> хувь"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Баруун талын хязгаар <xliff:g id="PERCENT">%1$d</xliff:g> хувь"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Ажлын профайл дахь <xliff:g id="APP">%1$s</xliff:g>-д хадгалсан"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Хувийн профайл дахь <xliff:g id="APP">%1$s</xliff:g>-д хадгалсан"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Файлс"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> энэ дэлгэцийн агшныг илрүүлсэн."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> болон бусад нээлттэй апп энэ дэлгэцийн агшныг илрүүлсэн."</string>
@@ -457,9 +458,13 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Ажлын аппыг үргэлжлүүлэх үү?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Үргэлжлүүлэх"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Түгжээтэй дэлгэц дээр виджетүүдийг хаах"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Виджетийг өөрчлөх"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Түгжээтэй дэлгэц дээрх виджетүүд"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"виджет сонгох"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Хэрэглэгчийг сэлгэх"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"эвхмэл цэс"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Энэ харилцан үйлдлийн бүх апп болон дата устах болно."</string>
@@ -626,8 +631,10 @@
<string name="volume_panel_collapsed_sliders" msgid="1413383759434791450">"Дууны түвшний гулсуулагчдыг хураасан"</string>
<string name="volume_panel_hint_mute" msgid="6962563028495243738">"%s-н дууг хаах"</string>
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"%s-н дууг нээх"</string>
- <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> дээр тоглуулж байна"</string>
+ <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> тоглуулж байна"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"Аудиог дараахад тоглуулна"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"Системийн UI Тохируулагч"</string>
<string name="status_bar" msgid="4357390266055077437">"Статус самбар"</string>
<string name="demo_mode" msgid="263484519766901593">"Системийн UI демо горим"</string>
@@ -655,8 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Хиймэл дагуул, холболт муу байна"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Хиймэл дагуул, холболт сайн байна"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Хиймэл дагуул, холболт боломжтой"</string>
- <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"Хиймэл дагуулд холбогдсон"</string>
- <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"Хиймэл дагуулд холбогдоогүй"</string>
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Хиймэл дагуул SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Ажлын профайл"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Зарим хүнд хөгжилтэй байж болох ч бүх хүнд тийм биш"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Системийн UI Tохируулагч нь Android хэрэглэгчийн интерфэйсийг тааруулах, өөрчлөх нэмэлт аргыг зааж өгөх болно. Эдгээр туршилтын тохиргоо нь цаашид өөрчлөгдөх, эвдрэх, алга болох магадлалтай. Үйлдлийг болгоомжтой хийнэ үү."</string>
@@ -861,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Хавтан нэмэх"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g> руу зөөнө үү"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g> байрлалд нэмнэ үү"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Байрлал буруу байна."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"<xliff:g id="POSITION">%1$d</xliff:g> байрлал"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Хавтан нэмсэн"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Хавтанг хассан"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index f597876..0aad7643 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"डाव्या सीमेपासून <xliff:g id="PERCENT">%1$d</xliff:g> टक्के"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"उजव्या सीमेपासून <xliff:g id="PERCENT">%1$d</xliff:g> टक्के"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"<xliff:g id="APP">%1$s</xliff:g> मधील कार्य प्रोफाइलमध्ये सेव्ह केला"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"<xliff:g id="APP">%1$s</xliff:g> मधील खाजगी प्रोफाइलमध्ये सेव्ह केले आहे"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"फाइल"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> ने हा स्क्रीनशॉट डिटेक्ट केला."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> आणि उघडलेल्या इतर अॅप्सनी हा स्क्रीनशॉट डिटेक्ट केला."</string>
@@ -459,6 +460,11 @@
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"लॉक स्क्रीनवरील विजेट बंद करा"</string>
<string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"विजेट कस्टमाइझ करा"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"लॉक स्क्रीनवरील विजेट"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"विजेट निवडा"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"वापरकर्ता स्विच करा"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"पुलडाउन मेनू"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"या सत्रातील सर्व अॅप्स आणि डेटा हटवला जाईल."</string>
@@ -627,6 +633,7 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"%s अनम्यूट करा"</string>
<string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> वर प्ले करत आहे"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"यावर ऑडिओ प्ले होईल"</string>
+ <string name="media_output_title_ongoing_call" msgid="208426888064112006">"यावर कॉल करत आहे"</string>
<string name="system_ui_tuner" msgid="1471348823289954729">"सिस्टम UI ट्युनर"</string>
<string name="status_bar" msgid="4357390266055077437">"स्टेटस बार"</string>
<string name="demo_mode" msgid="263484519766901593">"सिस्टम UI डेमो मोड"</string>
@@ -654,8 +661,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"सॅटेलाइट, खराब कनेक्शन"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"सॅटेलाइट, चांगले कनेक्शन"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"सॅटेलाइट, कनेक्शन उपलब्ध"</string>
- <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"उपग्रहाशी जोडलेले आहे"</string>
- <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"उपग्रहाशी जोडलेले नाही"</string>
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"सॅटेलाइट SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"कार्य प्रोफाईल"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"सर्वांसाठी नाही तर काहींसाठी मजेदार असू शकते"</string>
<string name="tuner_warning" msgid="1861736288458481650">"सिस्टम UI ट्युनर आपल्याला Android यूझर इंटरफेस ट्विक आणि कस्टमाइझ करण्याचे अनेक प्रकार देते. ही प्रयोगात्मक वैशिष्ट्ये बदलू शकतात, खंडित होऊ शकतात किंवा भविष्यातील रिलीज मध्ये कदाचित दिसणार नाहीत. सावधगिरी बाळगून पुढे सुरू ठेवा."</string>
@@ -860,6 +866,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"टाइल जोडा"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g> यावर हलवा"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g> स्थानावर जोडा"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"स्थान चुकीचे आहे."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"स्थान <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"टाइल जोडली"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"टाइल काढून टाकली"</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 9e3117d..60c028d 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Sempadan kiri <xliff:g id="PERCENT">%1$d</xliff:g> peratus"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Sempadan kanan <xliff:g id="PERCENT">%1$d</xliff:g> peratus"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Disimpan dalam <xliff:g id="APP">%1$s</xliff:g> dalam profil kerja"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Disimpan dalam <xliff:g id="APP">%1$s</xliff:g> pada profil peribadi"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Fail"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> telah mengesan tangkapan skrin ini."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> dan apl lain yang dibuka telah mengesan tangkapan skrin ini."</string>
@@ -235,7 +236,7 @@
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Bidai pemberitahuan."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Tetapan pantas."</string>
<string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Tetapan pantas dan Bidai pemberitahuan."</string>
- <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"Kunci skrin"</string>
+ <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"Skrin kunci"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Skrin kunci kerja"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Tutup"</string>
<string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"senyap sepenuhnya"</string>
@@ -459,6 +460,11 @@
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Tutup widget pada skrin kunci"</string>
<string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Sesuaikan widget"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widget pada skrin kunci"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"pilih widget"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Tukar pengguna"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu tarik turun"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Semua apl dan data dalam sesi ini akan dipadam."</string>
@@ -627,6 +633,7 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"nyahredamkan %s"</string>
<string name="media_output_label_title" msgid="872824698593182505">"Memainkan <xliff:g id="LABEL">%s</xliff:g> pada"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"Audio dimainkan pada"</string>
+ <string name="media_output_title_ongoing_call" msgid="208426888064112006">"Membuat panggilan"</string>
<string name="system_ui_tuner" msgid="1471348823289954729">"Penala UI Sistem"</string>
<string name="status_bar" msgid="4357390266055077437">"Bar status"</string>
<string name="demo_mode" msgid="263484519766901593">"Mod tunjuk cara UI sistem"</string>
@@ -654,8 +661,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satelit, sambungan yang lemah"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelit, sambungan yang baik"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, sambungan tersedia"</string>
- <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"Disambungkan kepada satelit"</string>
- <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"Tidak disambungkan kepada satelit"</string>
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS via Satelit"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Profil kerja"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Menarik untuk sesetengah orang tetapi bukan untuk semua"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Penala UI Sistem memberi anda cara tambahan untuk mengolah dan menyesuaikan antara muka Android. Ciri eksperimen ini boleh berubah, rosak atau hilang dalam keluaran masa hadapan. Teruskan dengan berhati-hati."</string>
@@ -860,6 +866,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Tambahkan jubin"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Alih ke <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Tambahkan pada kedudukan <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Kedudukan tidak sah."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Kedudukan <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Jubin ditambah"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Jubin dialih keluar"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 86345a8..dcbf837 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"ဘယ်ဘက်အနားသတ် <xliff:g id="PERCENT">%1$d</xliff:g> ရာခိုင်နှုန်း"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"ညာဘက်အနားသတ် <xliff:g id="PERCENT">%1$d</xliff:g> ရာခိုင်နှုန်း"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"အလုပ်ပရိုဖိုင်ရှိ <xliff:g id="APP">%1$s</xliff:g> တွင် သိမ်းထားသည်"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"သီးသန့် ပရိုဖိုင်ရှိ <xliff:g id="APP">%1$s</xliff:g> တွင် သိမ်းထားသည်"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"ဖိုင်များ"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> က ဤဖန်သားပြင်ဓာတ်ပုံကို တွေ့ရှိသည်။"</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> နှင့် အခြားဖွင့်ထားသော အက်ပ်များက ဤဖန်သားပြင်ဓာတ်ပုံကို တွေ့ရှိသည်။"</string>
@@ -274,7 +275,7 @@
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"သိမ်းထားသည်"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ချိတ်ဆက်မှုဖြုတ်ရန်"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"စသုံးရန်"</string>
- <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"မနက်ဖြန် အလိုအလျောက် ထပ်ဖွင့်ရန်"</string>
+ <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"မနက်ဖြန် အလိုအလျောက် ပြန်ဖွင့်ရန်"</string>
<string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"‘အမြန် မျှဝေပါ’ နှင့် Find My Device ကဲ့သို့ တူးလ်များသည် ဘလူးတုသ်သုံးသည်"</string>
<string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"မနက်ဖြန်နံနက်တွင် ဘလူးတုသ် ပွင့်ပါမည်"</string>
<string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"အော်ဒီယို မျှဝေခြင်း"</string>
@@ -457,9 +458,13 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"အလုပ်သုံးအက်ပ် ပြန်ဖွင့်မလား။"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"ပြန်ဖွင့်ရန်"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"လော့ခ်မျက်နှာပြင်ရှိ ဝိဂျက်များကို ပိတ်ရန်"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"ဝိဂျက်များကို စိတ်ကြိုက်လုပ်ရန်"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"လော့ခ်မျက်နှာပြင်ရှိ ဝိဂျက်များ"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"ဝိဂျက် ရွေးရန်"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"အသုံးပြုသူကို ပြောင်းလဲရန်"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ဆွဲချမီနူး"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ဒီချိတ်ဆက်မှု ထဲက အက်ပ်များ အားလုံး နှင့် ဒေတာကို ဖျက်ပစ်မည်။"</string>
@@ -626,8 +631,9 @@
<string name="volume_panel_collapsed_sliders" msgid="1413383759434791450">"အသံအတိုးအကျယ် ရွှေ့တုံးများ လျှော့ပြထားသည်"</string>
<string name="volume_panel_hint_mute" msgid="6962563028495243738">"%s အသံပိတ်ရန်"</string>
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"%s အသံပြန်ဖွင့်ရန်"</string>
- <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> ကို ဖွင့်နေသည်"</string>
+ <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> ဖွင့်မည့်နေရာ"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"အသံဖွင့်မည့်နေရာ"</string>
+ <string name="media_output_title_ongoing_call" msgid="208426888064112006">"ဖုန်းဆက်နေသည်"</string>
<string name="system_ui_tuner" msgid="1471348823289954729">"စနစ် UI ဖမ်းစက်"</string>
<string name="status_bar" msgid="4357390266055077437">"အခြေအနေပြနေရာ"</string>
<string name="demo_mode" msgid="263484519766901593">"စနစ် UI စရုပ်ပြမုဒ်"</string>
@@ -655,10 +661,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"ဂြိုဟ်တု၊ ချိတ်ဆက်မှု မကောင်းပါ"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"ဂြိုဟ်တု၊ ချိတ်ဆက်မှု ကောင်းသည်"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ဂြိုဟ်တု၊ ချိတ်ဆက်မှု ရနိုင်သည်"</string>
- <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
- <skip />
- <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
- <skip />
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satellite SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"အလုပ် ပရိုဖိုင်"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"အချို့သူများ အတွက် ပျော်စရာ ဖြစ်ပေမဲ့ အားလုံး အတွက် မဟုတ်ပါ"</string>
<string name="tuner_warning" msgid="1861736288458481650">"စနစ် UI Tuner က သင့်အတွက် Android အသုံးပြုသူ အင်တာဖေ့စ်ကို ပြောင်းရန်နှင့် စိတ်ကြိုက်ပြုလုပ်ရန် နည်းလမ်း အပိုများကို သင့်အတွက် စီစဉ်ပေးသည်။ အနာဂတ်ဗားရှင်းများတွင် ဤစမ်းသပ်အင်္ဂါရပ်များမှာ ပြောင်းလဲ၊ ပျက်စီး သို့မဟုတ် ပျောက်ကွယ်သွားနိုင်သည်။ သတိဖြင့် ရှေ့ဆက်ပါ။"</string>
@@ -863,6 +866,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"အကွက်ငယ်ကို ထည့်ရန်"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g> သို့ ရွှေ့ရန်"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g> အနေအထားသို့ ပေါင်းထည့်ရန်"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"နေရာ မမှန်ပါ။"</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"<xliff:g id="POSITION">%1$d</xliff:g> အနေအထား"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"အကွက်ငယ်ကို ထည့်ပြီးပါပြီ"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"အကွက်ငယ်ကို ဖယ်ရှားပြီးပါပြီ"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 4c68dda..2724a51 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Venstre grense <xliff:g id="PERCENT">%1$d</xliff:g> prosent"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Høyre grense <xliff:g id="PERCENT">%1$d</xliff:g> prosent"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Lagret i <xliff:g id="APP">%1$s</xliff:g> i jobbprofilen"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Lagret i <xliff:g id="APP">%1$s</xliff:g> i den private profilen"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Filer"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> har registrert denne skjermdumpen."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> og andre åpne apper har registrert denne skjermdumpen."</string>
@@ -457,9 +458,13 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Vil du slå på jobbapper igjen?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Slå på"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Lukk moduler på låseskjermen"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Tilpass moduler"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Moduler på låseskjermen"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"velg modul"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Bytt bruker"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"rullegardinmeny"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alle apper og data i denne økten blir slettet."</string>
@@ -628,6 +633,8 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"slå på lyden til %s"</string>
<string name="media_output_label_title" msgid="872824698593182505">"Spiller av <xliff:g id="LABEL">%s</xliff:g> på"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"Lyden spilles av på"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"System UI Tuner"</string>
<string name="status_bar" msgid="4357390266055077437">"Statusrad"</string>
<string name="demo_mode" msgid="263484519766901593">"Demomodus for systemgrensesnitt"</string>
@@ -655,10 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satellitt – dårlig tilkobling"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellitt – god tilkobling"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellitt – tilkobling tilgjengelig"</string>
- <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
- <skip />
- <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
- <skip />
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS-alarm via satellitt"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Work-profil"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Gøy for noen – ikke for alle"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Med System UI Tuner har du flere måter å justere og tilpasse Android-brukergrensesnittet på. Disse eksperimentelle funksjonene kan endres, avbrytes eller fjernes i fremtidige utgivelser. Fortsett med forbehold."</string>
@@ -863,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Legg til en infobrikke"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Flytt til <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Legg til posisjonen <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Posisjonen er ugyldig."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Posisjon <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"En infobrikke er lagt til"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"En infobrikke er fjernet"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 400fed0..1bbab4a 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"बायाँ किनाराबाट <xliff:g id="PERCENT">%1$d</xliff:g> प्रतिशत"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"दायाँ किनाराबाट <xliff:g id="PERCENT">%1$d</xliff:g> प्रतिशत"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"कार्य प्रोफाइलअन्तर्गत <xliff:g id="APP">%1$s</xliff:g> मा सेभ गरियो"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"निजी प्रोफाइलअन्तर्गत <xliff:g id="APP">%1$s</xliff:g> मा सेभ गरिएको छ"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Files"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> ले यो स्क्रिनसट भेट्टाएको छ।"</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> र खुला रहेका अन्य एपहरूले यो स्क्रिनसट भेट्टाएका छन्।"</string>
@@ -174,7 +175,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"प्याटर्न मिलेन"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"पासवर्ड मिलेन"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"अत्यन्तै धेरै पटक गलत प्रयास गरिए। \n <xliff:g id="NUMBER">%d</xliff:g>सेकेन्ड पछि पुनः प्रयास गर्नुहोस्।"</string>
- <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"आपत्कालीन"</string>
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"आपत्कालीन"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"फेरि प्रयास गर्नुहोस्। <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g> मध्ये <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> प्रयास।"</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"तपाईंको डेटा मेटाइने छ"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"तपाईंले अर्को पटक पनि गलत ढाँचा प्रविष्टि गर्नुभयो भने यो डिभाइसको डेटा मेटाइने छ।"</string>
@@ -459,6 +460,11 @@
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"लक स्क्रिनमा भएका विजेटहरू बन्द गर्नुहोस्"</string>
<string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"विजेटहरू कस्टमाइज गर्नुहोस्"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"लक स्क्रिनमा भएका विजेटहरू"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"विजेट चयन गर्नुहोस्"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"प्रयोगकर्ता फेर्नुहोस्"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"पुलडाउन मेनु"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"यो सत्रमा भएका सबै एपहरू र डेटा मेटाइने छ।"</string>
@@ -627,6 +633,7 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"%s अनम्युट गर्नुहोस्"</string>
<string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> प्ले गरिँदै छ"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"अडियो यसमा प्ले हुने छ"</string>
+ <string name="media_output_title_ongoing_call" msgid="208426888064112006">"कल चलिरहेको छ"</string>
<string name="system_ui_tuner" msgid="1471348823289954729">"सिस्टम UI ट्युनर"</string>
<string name="status_bar" msgid="4357390266055077437">"स्थिति पट्टी"</string>
<string name="demo_mode" msgid="263484519766901593">"सिस्टम UI को डेमो मोड"</string>
@@ -654,10 +661,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"स्याटलाइट, खराब कनेक्सन"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"स्याटलाइट, राम्रो कनेक्सन"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"स्याटलाइट, कनेक्सन उपलब्ध छ"</string>
- <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
- <skip />
- <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
- <skip />
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"स्याटलाइट SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"कार्य प्रोफाइल"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"केहीका लागि रमाइलो हुन्छ तर सबैका लागि होइन"</string>
<string name="tuner_warning" msgid="1861736288458481650">"सिस्टम UI ट्युनरले तपाईँलाई Android प्रयोगकर्ता इन्टरफेस आफू अनुकूल गर्न र ट्विक गर्न थप तरिकाहरू प्रदान गर्छ। यी प्रयोगात्मक सुविधाहरू भावी विमोचनमा परिवर्तन हुन, बिग्रिन वा हराउन सक्ने छन्। सावधानीपूर्वक अगाडि बढ्नुहोस्।"</string>
@@ -862,6 +866,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"टाइल हाल्नुहोस्"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"टाइल सारेर <xliff:g id="POSITION">%1$d</xliff:g> मा लैजानुहोस्"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"टाइल यो अवस्था <xliff:g id="POSITION">%1$d</xliff:g> मा हाल्नुहोस्"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"पोजिसन अवैध छ।"</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"स्थिति <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"टाइल हालियो"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"टाइल हटाइयो"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 8dcfe9c..1a831ac 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Linkergrens <xliff:g id="PERCENT">%1$d</xliff:g> procent"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Rechtergrens <xliff:g id="PERCENT">%1$d</xliff:g> procent"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Opgeslagen in <xliff:g id="APP">%1$s</xliff:g> in het werkprofiel."</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Opgeslagen in <xliff:g id="APP">%1$s</xliff:g> in het privéprofiel"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Bestanden"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> heeft dit screenshot waargenomen."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> en andere geopende apps hebben dit screenshot waargenomen."</string>
@@ -459,6 +460,11 @@
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Widgets op het vergrendelscherm sluiten"</string>
<string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Widgets aanpassen"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widgets op het vergrendelscherm"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"widget selecteren"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Gebruiker wijzigen"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"pull-downmenu"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alle apps en gegevens in deze sessie worden verwijderd."</string>
@@ -590,14 +596,14 @@
<string name="screen_pinning_exit" msgid="4553787518387346893">"App losgemaakt"</string>
<string name="stream_voice_call" msgid="7468348170702375660">"Bellen"</string>
<string name="stream_system" msgid="7663148785370565134">"Systeem"</string>
- <string name="stream_ring" msgid="7550670036738697526">"Bellen"</string>
+ <string name="stream_ring" msgid="7550670036738697526">"Beltoon"</string>
<string name="stream_music" msgid="2188224742361847580">"Media"</string>
<string name="stream_alarm" msgid="16058075093011694">"Wekker"</string>
<string name="stream_notification" msgid="7930294049046243939">"Melding"</string>
<string name="stream_bluetooth_sco" msgid="6234562365528664331">"Bluetooth"</string>
<string name="stream_dtmf" msgid="7322536356554673067">"Frequentie voor tweevoudige multitoon"</string>
<string name="stream_accessibility" msgid="3873610336741987152">"Toegankelijkheid"</string>
- <string name="volume_ringer_status_normal" msgid="1339039682222461143">"Bellen"</string>
+ <string name="volume_ringer_status_normal" msgid="1339039682222461143">"Beltoon"</string>
<string name="volume_ringer_status_vibrate" msgid="6970078708957857825">"Trillen"</string>
<string name="volume_ringer_status_silent" msgid="3691324657849880883">"Geluid staat uit"</string>
<string name="media_device_cast" msgid="4786241789687569892">"Casten"</string>
@@ -627,6 +633,7 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"geluid van %s aanzetten"</string>
<string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> wordt afgespeeld op"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"Audio wordt afgespeeld op"</string>
+ <string name="media_output_title_ongoing_call" msgid="208426888064112006">"Bellen actief"</string>
<string name="system_ui_tuner" msgid="1471348823289954729">"Systeem-UI-tuner"</string>
<string name="status_bar" msgid="4357390266055077437">"Statusbalk"</string>
<string name="demo_mode" msgid="263484519766901593">"Demomodus voor systeemgebruikersinterface"</string>
@@ -654,8 +661,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satelliet, slechte verbinding"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelliet, goede verbinding"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelliet, verbinding beschikbaar"</string>
- <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"Verbonden met satelliet"</string>
- <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"Niet verbonden met satelliet"</string>
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS via satelliet"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Werkprofiel"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Leuk voor sommige gebruikers, maar niet voor iedereen"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Met Systeem-UI-tuner beschikt u over extra manieren om de Android-gebruikersinterface aan te passen. Deze experimentele functies kunnen veranderen, vastlopen of verdwijnen in toekomstige releases. Ga voorzichtig verder."</string>
@@ -860,6 +866,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Tegel toevoegen"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Verplaatsen naar <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Toevoegen aan positie <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Positie ongeldig."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Positie <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Tegel toegevoegd"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Tegel verwijderd"</string>
@@ -1103,7 +1110,7 @@
<string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> apparaten geselecteerd"</string>
<string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(verbinding verbroken)"</string>
<string name="media_output_dialog_connect_failed" msgid="3080972621975339387">"Kan niet schakelen. Tik om het opnieuw te proberen."</string>
- <string name="media_output_dialog_pairing_new" msgid="5098212763195577270">"Een apparaat koppelen"</string>
+ <string name="media_output_dialog_pairing_new" msgid="5098212763195577270">"Apparaat koppelen"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Als je deze sessie wilt casten, open je de app."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Onbekende app"</string>
<string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Casten stoppen"</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index e164c3d..e64b1b4 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"ବାମ ସୀମାରେଖା <xliff:g id="PERCENT">%1$d</xliff:g> ଶତକଡ଼ା"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"ଡାହାଣ ସୀମାରେଖା <xliff:g id="PERCENT">%1$d</xliff:g> ଶତକଡ଼ା"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"ୱାର୍କ ପ୍ରୋଫାଇଲରେ ଥିବା <xliff:g id="APP">%1$s</xliff:g>ରେ ସେଭ କରାଯାଇଛି"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"ପ୍ରାଇଭେଟ ପ୍ରୋଫାଇଲରେ ଥିବା <xliff:g id="APP">%1$s</xliff:g>ରେ ସେଭ କରାଯାଇଛି"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"ଫାଇଲଗୁଡ଼ିକ"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> ଏହି ସ୍କ୍ରିନସଟକୁ ଚିହ୍ନଟ କରିଛି।"</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> ଏବଂ ଅନ୍ୟ ଓପନ ଆପ୍ସ ଏହି ସ୍କ୍ରିନସଟକୁ ଚିହ୍ନଟ କରିଛି।"</string>
@@ -457,9 +458,13 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"ୱାର୍କ ଆପ୍ସକୁ ପୁଣି ଚାଲୁ କରିବେ?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"ପୁଣି ଚାଲୁ କରନ୍ତୁ"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"ଲକ ସ୍କ୍ରିନରେ ଥିବା ୱିଜେଟଗୁଡ଼ିକୁ ବନ୍ଦ କରନ୍ତୁ"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"ୱିଜେଟଗୁଡ଼ିକୁ କଷ୍ଟମାଇଜ କରନ୍ତୁ"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"ଲକ ସ୍କ୍ରିନରେ ଥିବା ୱିଜେଟଗୁଡ଼ିକ"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"ୱିଜେଟ ଚୟନ କରନ୍ତୁ"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ୟୁଜର୍ ବଦଳାନ୍ତୁ"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ପୁଲଡାଉନ ମେନୁ"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ଏହି ସେସନର ସମସ୍ତ ଆପ୍ ଓ ଡାଟା ଡିଲିଟ୍ ହୋଇଯିବ।"</string>
@@ -628,6 +633,8 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"%sକୁ ଅନମ୍ୟୁଟ କରନ୍ତୁ"</string>
<string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g>ରେ ପ୍ଲେ କରାଯାଉଛି"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"ଅଡିଓ ଏଥିରେ ପ୍ଲେ ହେବ"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"ସିଷ୍ଟମ୍ UI ଟ୍ୟୁନର୍"</string>
<string name="status_bar" msgid="4357390266055077437">"ଷ୍ଟାଟସ୍ ବାର୍"</string>
<string name="demo_mode" msgid="263484519766901593">"ସିଷ୍ଟମ୍ UI ଡେମୋ ମୋଡ୍"</string>
@@ -655,8 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"ସାଟେଲାଇଟ, ଦୁର୍ବଳ କନେକ୍ସନ"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"ସାଟେଲାଇଟ, ଭଲ କନେକ୍ସନ"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ସାଟେଲାଇଟ, କନେକ୍ସନ ଉପଲବ୍ଧ"</string>
- <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"ସେଟେଲାଇଟ ସହ କନେକ୍ଟ ହୋଇଛନ୍ତି"</string>
- <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"ସେଟେଲାଇଟ ସହ କନେକ୍ଟ ହୋଇନାହାଁନ୍ତି"</string>
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"ସେଟେଲାଇଟ SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"ୱର୍କ ପ୍ରୋଫାଇଲ୍"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"କେତେକଙ୍କ ପାଇଁ ମଜାଦାର, କିନ୍ତୁ ସମସ୍ତଙ୍କ ପାଇଁ ନୁହେଁ"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Android ୟୁଜର୍ ଇଣ୍ଟରଫେସ୍ ବଦଳାଇବାକୁ ତଥା ନିଜ ପସନ୍ଦ ଅନୁଯାୟୀ କରିବାକୁ ସିଷ୍ଟମ୍ UI ଟ୍ୟୁନର୍ ଆପଣଙ୍କୁ ଅତିରିକ୍ତ ଉପାୟ ପ୍ରଦାନ କରେ। ଏହି ପରୀକ୍ଷାମୂଳକ ସୁବିଧାମାନ ବଦଳିପାରେ, ଭାଙ୍ଗିପାରେ କିମ୍ବା ଭବିଷ୍ୟତର ରିଲିଜ୍ଗୁଡ଼ିକରେ ନଦେଖାଯାଇପାରେ। ସତର୍କତାର ସହ ଆଗକୁ ବଢ଼ନ୍ତୁ।"</string>
@@ -861,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"ଟାଇଲ୍ ଯୋଗ କରନ୍ତୁ"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g>କୁ ମୁଭ୍ କରନ୍ତୁ"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g> ଅବସ୍ଥିତିରେ ଯୋଗ କରନ୍ତୁ"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"ଅବସ୍ଥିତି ଅବୈଧ ଅଟେ।"</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"ଅବସ୍ଥିତି <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"ଟାଇଲ୍ ଯୋଗ କରାଯାଇଛି"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"ଟାଇଲ୍ କାଢ଼ି ଦିଆଯାଇଛି"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 4e43e17..394d790 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"ਖੱਬੇ ਪਾਸੇ ਵਾਲੀ ਸੀਮਾ <xliff:g id="PERCENT">%1$d</xliff:g> ਫ਼ੀਸਦ"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"ਸੱਜੇ ਪਾਸੇ ਵਾਲੀ ਸੀਮਾ <xliff:g id="PERCENT">%1$d</xliff:g> ਫ਼ੀਸਦ"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਵਿੱਚ <xliff:g id="APP">%1$s</xliff:g> ਵਿੱਚ ਰੱਖਿਅਤ ਕੀਤਾ ਗਿਆ"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"<xliff:g id="APP">%1$s</xliff:g> ਦੇ ਨਿੱਜੀ ਪ੍ਰੋਫਾਈਲ ਵਿੱਚ ਰੱਖਿਅਤ ਕੀਤਾ ਗਿਆ"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"ਫ਼ਾਈਲਾਂ"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> ਨੂੰ ਇਸ ਸਕ੍ਰੀਨਸ਼ਾਟ ਦਾ ਪਤਾ ਲੱਗਿਆ ਹੈ।"</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> ਅਤੇ ਹੋਰ ਖੁੱਲ੍ਹੀਆਂ ਐਪਾਂ ਨੂੰ ਇਸ ਸਕ੍ਰੀਨਸ਼ਾਟ ਦਾ ਪਤਾ ਲੱਗਿਆ ਹੈ।"</string>
@@ -457,9 +458,13 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"ਕੰਮ ਸੰਬੰਧੀ ਐਪਾਂ ਤੋਂ ਰੋਕ ਹਟਾਈਏ?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"ਰੋਕ ਹਟਾਓ"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"ਲਾਕ ਸਕ੍ਰੀਨ \'ਤੇ ਵਿਜੇਟ ਬੰਦ ਕਰੋ"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"ਵਿਜੇਟ ਵਿਉਂਤਬੱਧ ਕਰੋ"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"ਲਾਕ ਸਕ੍ਰੀਨ \'ਤੇ ਵਿਜੇਟ"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"ਵਿਜੇਟ ਚੁਣੋ"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ਵਰਤੋਂਕਾਰ ਸਵਿੱਚ ਕਰੋ"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ਪੁੱਲਡਾਊਨ ਮੀਨੂ"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ਇਸ ਸੈਸ਼ਨ ਵਿਚਲੀਆਂ ਸਾਰੀਆਂ ਐਪਾਂ ਅਤੇ ਡਾਟੇ ਨੂੰ ਮਿਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ।"</string>
@@ -628,6 +633,8 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"%s ਨੂੰ ਅਣਮਿਊਟ ਕਰੋ"</string>
<string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> ਚਲਾਇਆ ਜਾ ਰਿਹਾ ਹੈ"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"ਆਡੀਓ ਇਸ \'ਤੇ ਚੱਲੇਗੀ"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"System UI ਟਿਊਨਰ"</string>
<string name="status_bar" msgid="4357390266055077437">"ਸਥਿਤੀ ਪੱਟੀ"</string>
<string name="demo_mode" msgid="263484519766901593">"ਸਿਸਟਮ UI ਡੈਮੋ ਮੋਡ"</string>
@@ -655,8 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"ਸੈਟੇਲਾਈਟ, ਕਨੈਕਸ਼ਨ ਖਰਾਬ ਹੈ"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"ਸੈਟੇਲਾਈਟ, ਕਨੈਕਸ਼ਨ ਵਧੀਆ ਹੈ"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ਸੈਟੇਲਾਈਟ, ਕਨੈਕਸ਼ਨ ਉਪਲਬਧ ਹੈ"</string>
- <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"ਸੈਟੇਲਾਈਟ ਨਾਲ ਕਨੈਕਟ ਹੈ"</string>
- <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"ਸੈਟੇਲਾਈਟ ਨਾਲ ਕਨੈਕਟ ਨਹੀਂ ਹੈ"</string>
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"ਸੈਟੇਲਾਈਟ SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"ਕੁਝ ਵਾਸਤੇ ਤਾਂ ਮਜ਼ੇਦਾਰ ਹੈ ਲੇਕਿਨ ਸਾਰਿਆਂ ਵਾਸਤੇ ਨਹੀਂ"</string>
<string name="tuner_warning" msgid="1861736288458481650">"ਸਿਸਟਮ UI ਟਿਊਨਰ ਤੁਹਾਨੂੰ Android ਵਰਤੋਂਕਾਰ ਇੰਟਰਫ਼ੇਸ ਤਬਦੀਲ ਕਰਨ ਅਤੇ ਵਿਉਂਤਬੱਧ ਕਰਨ ਲਈ ਵਾਧੂ ਤਰੀਕੇ ਦਿੰਦਾ ਹੈ। ਇਹ ਪ੍ਰਯੋਗਾਤਮਿਕ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਭਵਿੱਖ ਦੀ ਰੀਲੀਜ਼ ਵਿੱਚ ਬਦਲ ਸਕਦੀਆਂ ਹਨ, ਟੁੱਟ ਸਕਦੀਆਂ ਹਨ, ਜਾਂ ਅਲੋਪ ਹੋ ਸਕਦੀਆਂ ਹਨ। ਸਾਵਧਾਨੀ ਨਾਲ ਅੱਗੇ ਵੱਧੋ।"</string>
@@ -861,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"ਟਾਇਲ ਸ਼ਾਮਲ ਕਰੋ"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g> \'ਤੇ ਲਿਜਾਓ"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g> ਸਥਾਨ \'ਤੇ ਸ਼ਾਮਲ ਕਰੋ"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"ਮੌਜੂਦਾ ਥਾਂ ਅਵੈਧ ਹੈ।"</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"ਸਥਾਨ <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"ਟਾਇਲ ਨੂੰ ਸ਼ਾਮਲ ਕੀਤਾ ਗਿਆ"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"ਟਾਇਲ ਨੂੰ ਹਟਾ ਦਿੱਤਾ ਗਿਆ"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index f57fe29..9208628 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Przycięcie lewej krawędzi o <xliff:g id="PERCENT">%1$d</xliff:g> procent"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Przycięcie prawej krawędzi o <xliff:g id="PERCENT">%1$d</xliff:g> procent"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Zapisano w aplikacji <xliff:g id="APP">%1$s</xliff:g> w profilu służbowym"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Zapisano w aplikacji <xliff:g id="APP">%1$s</xliff:g> w profilu prywatnym"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Pliki"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"Aplikacja <xliff:g id="APPNAME">%1$s</xliff:g> wykryła ten zrzut ekranu."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"Aplikacja <xliff:g id="APPNAME">%1$s</xliff:g> i inne aplikacje wykryły ten zrzut ekranu."</string>
@@ -275,7 +276,7 @@
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"rozłącz"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktywuj"</string>
<string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Automatycznie włącz ponownie jutro"</string>
- <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Funkcje takie jak szybkie udostępnianie czy Znajdź moje urządzenie korzystają z Bluetootha"</string>
+ <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Bluetootha używają funkcje takie jak szybkie udostępnianie czy Znajdź moje urządzenie"</string>
<string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Bluetooth włączy się jutro rano"</string>
<string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Udostępnianie dźwięku"</string>
<string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Udostępniam dźwięk"</string>
@@ -459,6 +460,11 @@
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Zamknij widżety na ekranie blokady"</string>
<string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Dostosuj widżety"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widżety na ekranie blokady"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"wybierz widżet"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Przełącz użytkownika"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Wszystkie aplikacje i dane w tej sesji zostaną usunięte."</string>
@@ -627,6 +633,8 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"wyłącz wyciszenie: %s"</string>
<string name="media_output_label_title" msgid="872824698593182505">"Odtwarzam <xliff:g id="LABEL">%s</xliff:g> na"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"Wyjścia dźwięku:"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"Kalibrator System UI"</string>
<string name="status_bar" msgid="4357390266055077437">"Pasek stanu"</string>
<string name="demo_mode" msgid="263484519766901593">"Tryb demonstracyjny interfejsu"</string>
@@ -654,10 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satelita – połączenie słabe"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelita – połączenie dobre"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelita – połączenie dostępne"</string>
- <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
- <skip />
- <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
- <skip />
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satelitarne połączenie alarmowe"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Profil służbowy"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Dobra zabawa, ale nie dla każdego"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Kalibrator System UI udostępnia dodatkowe sposoby dostrajania i dostosowywania interfejsu Androida. Te eksperymentalne funkcje mogą się zmienić, popsuć lub zniknąć w przyszłych wersjach. Zachowaj ostrożność."</string>
@@ -862,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Dodaj kartę"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Przenieś do pozycji <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Dodaj w pozycji <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Nieprawidłowa pozycja."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Pozycja <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Dodano kartę"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Usunięto kartę"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 91b7a29..60472c8 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Borda esquerda em <xliff:g id="PERCENT">%1$d</xliff:g> por cento"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Borda direita em <xliff:g id="PERCENT">%1$d</xliff:g> por cento"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Salva no app <xliff:g id="APP">%1$s</xliff:g> no perfil de trabalho"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Salva no app <xliff:g id="APP">%1$s</xliff:g> no perfil particular"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Files"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"O app <xliff:g id="APPNAME">%1$s</xliff:g> detectou essa captura de tela."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> e outros apps abertos detectaram essa captura de tela."</string>
@@ -457,9 +458,13 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Reativar apps de trabalho?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Reativar"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Fechar widgets na tela de bloqueio"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Personalizar widgets"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widgets na tela de bloqueio"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"selecionar widget"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Trocar usuário"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu suspenso"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Todos os apps e dados nesta sessão serão excluídos."</string>
@@ -554,7 +559,7 @@
<string name="monitoring_description_personal_profile_named_vpn" msgid="5083909710727365452">"Seus apps pessoais estão conectados à Internet via <xliff:g id="VPN_APP">%1$s</xliff:g>. As atividades de rede, incluindo e-mails e dados de navegação, estão visíveis para o provedor de VPN."</string>
<string name="monitoring_description_vpn_settings_separator" msgid="8292589617720435430">" "</string>
<string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"Abrir configurações de VPN"</string>
- <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Este dispositivo é gerenciado pelo seu familiar responsável, que pode ver e gerenciar informações como os apps que você usa, sua localização e seu tempo de uso."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Este dispositivo é gerenciado pelo seu familiar responsável, que pode ver e gerenciar informações como os apps que você usa, sua localização e seu tempo de tela."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Desbloqueado pelo TrustAgent"</string>
<string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"O dispositivo foi bloqueado devido a muitas tentativas de autenticação"</string>
@@ -591,7 +596,7 @@
<string name="screen_pinning_exit" msgid="4553787518387346893">"App liberado"</string>
<string name="stream_voice_call" msgid="7468348170702375660">"Ligar"</string>
<string name="stream_system" msgid="7663148785370565134">"Sistema"</string>
- <string name="stream_ring" msgid="7550670036738697526">"Tocar"</string>
+ <string name="stream_ring" msgid="7550670036738697526">"Toques"</string>
<string name="stream_music" msgid="2188224742361847580">"Mídia"</string>
<string name="stream_alarm" msgid="16058075093011694">"Alarme"</string>
<string name="stream_notification" msgid="7930294049046243939">"Notificação"</string>
@@ -627,7 +632,9 @@
<string name="volume_panel_hint_mute" msgid="6962563028495243738">"desativar o som de %s"</string>
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"ativar o som de %s"</string>
<string name="media_output_label_title" msgid="872824698593182505">"Tocando <xliff:g id="LABEL">%s</xliff:g> em"</string>
- <string name="media_output_title_without_playing" msgid="3825663683169305013">"O áudio vai tocar em"</string>
+ <string name="media_output_title_without_playing" msgid="3825663683169305013">"Onde o áudio vai tocar?"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"Sintonizador System UI"</string>
<string name="status_bar" msgid="4357390266055077437">"Barra de status"</string>
<string name="demo_mode" msgid="263484519766901593">"Modo de demonstração da interface do sistema"</string>
@@ -655,10 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satélite, conexão ruim"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satélite, conexão boa"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satélite, conexão disponível"</string>
- <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
- <skip />
- <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
- <skip />
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS via satélite"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Perfil de trabalho"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Diversão para alguns, mas não para todos"</string>
<string name="tuner_warning" msgid="1861736288458481650">"O sintonizador System UI fornece maneiras adicionais de ajustar e personalizar a interface do usuário do Android. Esses recursos experimentais podem mudar, falhar ou desaparecer nas versões futuras. Prossiga com cuidado."</string>
@@ -863,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Adicionar bloco"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Mover para <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Adicionar à posição <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Posição inválida."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Posição <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Bloco adicionado"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Bloco removido"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 41d092a..3b9bebb 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Limite esquerdo de <xliff:g id="PERCENT">%1$d</xliff:g> por cento"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Limite direito de <xliff:g id="PERCENT">%1$d</xliff:g> por cento"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Guardada na app <xliff:g id="APP">%1$s</xliff:g> no perfil de trabalho"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Guardada na app <xliff:g id="APP">%1$s</xliff:g> no perfil privado"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Ficheiros"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"A app <xliff:g id="APPNAME">%1$s</xliff:g> detetou esta captura de ecrã."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"A app <xliff:g id="APPNAME">%1$s</xliff:g> e outras apps abertas detetaram esta captura de ecrã."</string>
@@ -457,9 +458,13 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Retomar apps de trabalho?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Retomar"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Fechar widgets no ecrã de bloqueio"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Personalizar widgets"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widgets no ecrã de bloqueio"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"selecionar widget"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Mudar utilizador"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu pendente"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Todas as apps e dados desta sessão serão eliminados."</string>
@@ -626,8 +631,9 @@
<string name="volume_panel_collapsed_sliders" msgid="1413383759434791450">"Controlos de deslize do volume reduzidos"</string>
<string name="volume_panel_hint_mute" msgid="6962563028495243738">"desativar o som de %s"</string>
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"reativar o som de %s"</string>
- <string name="media_output_label_title" msgid="872824698593182505">"A ouvir <xliff:g id="LABEL">%s</xliff:g> em"</string>
+ <string name="media_output_label_title" msgid="872824698593182505">"A ouvir <xliff:g id="LABEL">%s</xliff:g> em:"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"Áudio ouvido em:"</string>
+ <string name="media_output_title_ongoing_call" msgid="208426888064112006">"Chamada em curso"</string>
<string name="system_ui_tuner" msgid="1471348823289954729">"Sintonizador da interface do sistema"</string>
<string name="status_bar" msgid="4357390266055077437">"Barra de estado"</string>
<string name="demo_mode" msgid="263484519766901593">"Modo de demonstração da IU do sistema"</string>
@@ -655,8 +661,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satélite, ligação fraca"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satélite, boa ligação"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satélite, ligação disponível"</string>
- <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"Ligação de satélite estabelecida"</string>
- <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"Não tem uma ligação de satélite estabelecida"</string>
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satélite SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Perfil de trabalho"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Diversão para alguns, mas não para todos"</string>
<string name="tuner_warning" msgid="1861736288458481650">"O Sintonizador da interface do sistema disponibiliza-lhe formas adicionais ajustar e personalizar a interface do utilizador do Android. Estas funcionalidades experimentais podem ser alteradas, deixar de funcionar ou desaparecer em versões futuras. Prossiga com cuidado."</string>
@@ -861,6 +866,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Adicionar cartão"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Mova para <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Adicione à posição <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Posição inválida."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Posição <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Cartão adicionado"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Cartão removido"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 91b7a29..60472c8 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Borda esquerda em <xliff:g id="PERCENT">%1$d</xliff:g> por cento"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Borda direita em <xliff:g id="PERCENT">%1$d</xliff:g> por cento"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Salva no app <xliff:g id="APP">%1$s</xliff:g> no perfil de trabalho"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Salva no app <xliff:g id="APP">%1$s</xliff:g> no perfil particular"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Files"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"O app <xliff:g id="APPNAME">%1$s</xliff:g> detectou essa captura de tela."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> e outros apps abertos detectaram essa captura de tela."</string>
@@ -457,9 +458,13 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Reativar apps de trabalho?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Reativar"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Fechar widgets na tela de bloqueio"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Personalizar widgets"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widgets na tela de bloqueio"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"selecionar widget"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Trocar usuário"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu suspenso"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Todos os apps e dados nesta sessão serão excluídos."</string>
@@ -554,7 +559,7 @@
<string name="monitoring_description_personal_profile_named_vpn" msgid="5083909710727365452">"Seus apps pessoais estão conectados à Internet via <xliff:g id="VPN_APP">%1$s</xliff:g>. As atividades de rede, incluindo e-mails e dados de navegação, estão visíveis para o provedor de VPN."</string>
<string name="monitoring_description_vpn_settings_separator" msgid="8292589617720435430">" "</string>
<string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"Abrir configurações de VPN"</string>
- <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Este dispositivo é gerenciado pelo seu familiar responsável, que pode ver e gerenciar informações como os apps que você usa, sua localização e seu tempo de uso."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Este dispositivo é gerenciado pelo seu familiar responsável, que pode ver e gerenciar informações como os apps que você usa, sua localização e seu tempo de tela."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Desbloqueado pelo TrustAgent"</string>
<string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"O dispositivo foi bloqueado devido a muitas tentativas de autenticação"</string>
@@ -591,7 +596,7 @@
<string name="screen_pinning_exit" msgid="4553787518387346893">"App liberado"</string>
<string name="stream_voice_call" msgid="7468348170702375660">"Ligar"</string>
<string name="stream_system" msgid="7663148785370565134">"Sistema"</string>
- <string name="stream_ring" msgid="7550670036738697526">"Tocar"</string>
+ <string name="stream_ring" msgid="7550670036738697526">"Toques"</string>
<string name="stream_music" msgid="2188224742361847580">"Mídia"</string>
<string name="stream_alarm" msgid="16058075093011694">"Alarme"</string>
<string name="stream_notification" msgid="7930294049046243939">"Notificação"</string>
@@ -627,7 +632,9 @@
<string name="volume_panel_hint_mute" msgid="6962563028495243738">"desativar o som de %s"</string>
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"ativar o som de %s"</string>
<string name="media_output_label_title" msgid="872824698593182505">"Tocando <xliff:g id="LABEL">%s</xliff:g> em"</string>
- <string name="media_output_title_without_playing" msgid="3825663683169305013">"O áudio vai tocar em"</string>
+ <string name="media_output_title_without_playing" msgid="3825663683169305013">"Onde o áudio vai tocar?"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"Sintonizador System UI"</string>
<string name="status_bar" msgid="4357390266055077437">"Barra de status"</string>
<string name="demo_mode" msgid="263484519766901593">"Modo de demonstração da interface do sistema"</string>
@@ -655,10 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satélite, conexão ruim"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satélite, conexão boa"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satélite, conexão disponível"</string>
- <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
- <skip />
- <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
- <skip />
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS via satélite"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Perfil de trabalho"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Diversão para alguns, mas não para todos"</string>
<string name="tuner_warning" msgid="1861736288458481650">"O sintonizador System UI fornece maneiras adicionais de ajustar e personalizar a interface do usuário do Android. Esses recursos experimentais podem mudar, falhar ou desaparecer nas versões futuras. Prossiga com cuidado."</string>
@@ -863,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Adicionar bloco"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Mover para <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Adicionar à posição <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Posição inválida."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Posição <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Bloco adicionado"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Bloco removido"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 7ccaa5a..84d68e70 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Marginea stângă la <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Marginea dreaptă la <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Salvată în <xliff:g id="APP">%1$s</xliff:g> în profilul de serviciu"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Salvată în <xliff:g id="APP">%1$s</xliff:g> în profilul privat"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Fișiere"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> a detectat această captură de ecran."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> și alte aplicații deschise au detectat această captură de ecran."</string>
@@ -457,9 +458,13 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Reactivezi aplicații de lucru?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Reactivează"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Închide widgeturile de pe ecranul de blocare"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Personalizează widgeturile"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widgeturi pe ecranul de blocare"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"selectează un widget"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Schimbă utilizatorul"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"meniu vertical"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Toate aplicațiile și datele din această sesiune vor fi șterse."</string>
@@ -628,6 +633,8 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"activează sunetul pentru %s"</string>
<string name="media_output_label_title" msgid="872824698593182505">"Se redă <xliff:g id="LABEL">%s</xliff:g> pe"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"Conținutul audio se va reda pe"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"System UI Tuner"</string>
<string name="status_bar" msgid="4357390266055077437">"Bară de stare"</string>
<string name="demo_mode" msgid="263484519766901593">"Mod demonstrativ pentru IU sistem"</string>
@@ -655,10 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satelit, conexiune slabă"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelit, conexiune bună"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, conexiune disponibilă"</string>
- <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
- <skip />
- <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
- <skip />
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS prin satelit"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Profil de serviciu"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Distractiv pentru unii, dar nu pentru toată lumea"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner oferă modalități suplimentare de a ajusta și a personaliza interfața de utilizare Android. Aceste funcții experimentale pot să se schimbe, să se blocheze sau să dispară din versiunile viitoare. Continuă cu prudență."</string>
@@ -863,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Adaugă un card"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Mută pe poziția <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Adaugă pe poziția <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Poziție nevalidă."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Poziția <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Cardul a fost adăugat"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Cardul a fost eliminat"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index fad12e4..c405469 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Граница слева: <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Граница справа: <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Скриншот сохранен в рабочем профиле в приложении <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Сохранено в приложении \"<xliff:g id="APP">%1$s</xliff:g>\" в личном профиле"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Файлы"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"Приложение \"<xliff:g id="APPNAME">%1$s</xliff:g>\" обнаружило создание скриншота."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"Приложение \"<xliff:g id="APPNAME">%1$s</xliff:g>\" и другие запущенные продукты обнаружили создание скриншота."</string>
@@ -265,7 +266,7 @@
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Не беспокоить"</string>
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Нет доступных сопряженных устройств"</string>
- <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Нажмите, чтобы подключить или отключить устройство"</string>
+ <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Нажмите, чтобы подключить или отключить устройство."</string>
<string name="pair_new_bluetooth_devices" msgid="4601767620843349645">"Подключить устройство"</string>
<string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Все"</string>
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Использовать"</string>
@@ -459,6 +460,11 @@
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Закрыть виджеты на заблокированном экране"</string>
<string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Настроить виджеты"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Виджеты на заблокированном экране"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"выбрать виджет"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Сменить пользователя."</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"раскрывающееся меню"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Все приложения и данные этого профиля будут удалены."</string>
@@ -627,6 +633,8 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"включить звук: %s"</string>
<string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> – запущено здесь:"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"Проигрывание аудио:"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"System UI Tuner"</string>
<string name="status_bar" msgid="4357390266055077437">"Строка состояния"</string>
<string name="demo_mode" msgid="263484519766901593">"Интерфейс системы: деморежим"</string>
@@ -654,10 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Спутниковая связь, плохое качество соединения"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Спутниковая связь, хорошее качество соединения"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Доступно соединение по спутниковой связи"</string>
- <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
- <skip />
- <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
- <skip />
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Спутниковый SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Рабочий профиль"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Внимание!"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner позволяет настраивать интерфейс устройства Android по вашему вкусу. В будущем эта экспериментальная функция может измениться, перестать работать или исчезнуть."</string>
@@ -862,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Добавить панель"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Переместить на позицию <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Добавить на позицию <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Недопустимое расположение."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Позиция <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Панель добавлена"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Панель удалена"</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 0473cd6..37bb23a 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"වම් සීමාව සියයට <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"දකුණු සීමාව සියයට <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"කාර්යාල පැතිකඩේ <xliff:g id="APP">%1$s</xliff:g> තුළ සුරකින ලදි"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"පුද්ගලික පැතිකඩ තුළ <xliff:g id="APP">%1$s</xliff:g> තුළ සුරකින ලදි"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"ගොනු"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> මෙම තිර රුව අනාවරණය කර ගෙන ඇත."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> සහ අනෙකුත් විවෘත යෙදුම් මෙම තිර රුව අනාවරණය කර ගෙන ඇත."</string>
@@ -459,6 +460,11 @@
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"අගුළු තිරයෙහි විජට් වසන්න"</string>
<string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"විජට්ටු අභිරුචි කරන්න"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"අගුළු තිරයෙහි විජට්"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"විජට්ටුව තෝරන්න"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"පරිශීලක මාරුව"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"නිපතන මෙනුව"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"මෙම සැසියේ සියළුම යෙදුම් සහ දත්ත මකාවී."</string>
@@ -627,6 +633,8 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"%s නිහඬ නොකරන්න"</string>
<string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> වාදනය කරන්නේ"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"ශ්රව්ය වාදනය වනු ඇත්තේ"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"පද්ධති UI සුසරකය"</string>
<string name="status_bar" msgid="4357390266055077437">"තත්ත්ව තීරුව"</string>
<string name="demo_mode" msgid="263484519766901593">"පද්ධති UI ආදර්ශන ප්රකාරය"</string>
@@ -654,10 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"චන්ද්රිකාව, දුර්වල සම්බන්ධතාවය"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"චන්ද්රිකාව, හොඳ සම්බන්ධතාවයක්"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"චන්ද්රිකාව, සම්බන්ධතාවය තිබේ"</string>
- <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
- <skip />
- <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
- <skip />
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"චන්ද්රිකා SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"කාර්යාල පැතිකඩ"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"සමහරක් දේවල් වලට විනෝදයි, නමුත් සියල්ලටම නොවේ"</string>
<string name="tuner_warning" msgid="1861736288458481650">"පද්ධති UI සුසරකය ඔබට Android පරිශීලක අතුරු මුහුණත වෙනස් කිරීමට හෝ අභිරුචිකරණය කිරීමට අමතර ක්රම ලබා දේ. මෙම පර්යේෂණාත්මක අංග ඉදිරි නිකුත් වීම් වල වෙනස් වීමට, වැඩ නොකිරීමට, හෝ නැතිවීමට හැක. ප්රවේශමෙන් ඉදිරියට යන්න."</string>
@@ -862,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"ටයිල් එක් කරන්න"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g> වෙත ගෙන යන්න"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g> ස්ථානයට එක් කරන්න"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"ස්ථානය අවලංගුයි."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"ස්ථානය <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"ටයිල් එක එක් කරන ලදි"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"ටයිල් ඉවත් කරන ලදි"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 9d71dbd..675a345 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"<xliff:g id="PERCENT">%1$d</xliff:g> %% ľavej hranice"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"<xliff:g id="PERCENT">%1$d</xliff:g> %% pravej hranice"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Uložená v aplikácii <xliff:g id="APP">%1$s</xliff:g> v pracovnom profile"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Uložené v aplikácii <xliff:g id="APP">%1$s</xliff:g> v súkromnom profile"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Files"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"Aplikácia <xliff:g id="APPNAME">%1$s</xliff:g> zaznamenala túto snímku obrazovky."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> a ďalšie otvorené aplikácie zaznamenali túto snímku obrazovky."</string>
@@ -459,6 +460,11 @@
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Zavrieť miniaplikácie na uzamknutej obrazovke"</string>
<string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Prispôsobiť miniaplikácie"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Miniaplikácie na uzamknutej obrazovke"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"vybrať miniaplikáciu"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Prepnutie používateľa"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"rozbaľovacia ponuka"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Všetky aplikácie a údaje v tejto relácii budú odstránené."</string>
@@ -588,7 +594,7 @@
<string name="screen_pinning_negative" msgid="6882816864569211666">"Nie, vďaka"</string>
<string name="screen_pinning_start" msgid="7483998671383371313">"Aplikácia bola pripnutá"</string>
<string name="screen_pinning_exit" msgid="4553787518387346893">"Aplikácia bola odopnutá"</string>
- <string name="stream_voice_call" msgid="7468348170702375660">"Zavolať"</string>
+ <string name="stream_voice_call" msgid="7468348170702375660">"Hovor"</string>
<string name="stream_system" msgid="7663148785370565134">"Systém"</string>
<string name="stream_ring" msgid="7550670036738697526">"Zvonenie"</string>
<string name="stream_music" msgid="2188224742361847580">"Médiá"</string>
@@ -627,6 +633,8 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"zapnete zvuk %s"</string>
<string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> sa prehráva v:"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"Zvuk sa prehrá cez"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"Tuner používateľského rozhrania systému"</string>
<string name="status_bar" msgid="4357390266055077437">"Stavový riadok"</string>
<string name="demo_mode" msgid="263484519766901593">"Ukážka používateľského rozhrania systému"</string>
@@ -654,10 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satelit, slabá kvalita pripojenia"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelit, dobrá kvalita pripojenia"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, pripojenie je k dispozícii"</string>
- <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
- <skip />
- <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
- <skip />
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Pomoc cez satelit"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Pracovný profil"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Pri používaní tuneru postupujte opatrne"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Tuner používateľského rozhrania systému poskytujte ďalšie spôsoby ladenia a prispôsobenia používateľského rozhrania Android. Tieto experimentálne funkcie sa môžu v budúcich verziách zmeniť, ich poskytovanie môže byť prerušené alebo môžu byť odstránené. Pokračujte opatrne."</string>
@@ -862,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Pridať kartu"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Presunúť na <xliff:g id="POSITION">%1$d</xliff:g>. pozíciu"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Pridať na <xliff:g id="POSITION">%1$d</xliff:g>. pozíciu"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Pozícia je neplatná."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"<xliff:g id="POSITION">%1$d</xliff:g>. pozícia"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Karta bola pridaná"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Karta bola odstránená"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index d41de93..f97d662 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Meja levo <xliff:g id="PERCENT">%1$d</xliff:g> odstotkov"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Meja desno <xliff:g id="PERCENT">%1$d</xliff:g> odstotkov"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Shranjeno v aplikaciji <xliff:g id="APP">%1$s</xliff:g> v delovnem profilu"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Shranjeno v aplikaciji <xliff:g id="APP">%1$s</xliff:g> v zasebnem profilu"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Datoteke"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"Aplikacija <xliff:g id="APPNAME">%1$s</xliff:g> je zaznala ta posnetek zaslona."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> in druge odprte aplikacije so zaznale ta posnetek zaslona."</string>
@@ -459,6 +460,11 @@
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Zapiranje pripomočkov na zaklenjenem zaslonu"</string>
<string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Prilagajanje pripomočkov"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Pripomočki na zaklenjenem zaslonu"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"izberite pripomoček"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Preklop med uporabniki"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"spustni meni"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Vse aplikacije in podatki v tej seji bodo izbrisani."</string>
@@ -627,6 +633,8 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"vklop zvoka %s"</string>
<string name="media_output_label_title" msgid="872824698593182505">"Predvajanje »<xliff:g id="LABEL">%s</xliff:g>« v"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"Zvok bo predvajan v"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"Uglaševalnik uporabniškega vmesnika sistema"</string>
<string name="status_bar" msgid="4357390266055077437">"Vrstica stanja"</string>
<string name="demo_mode" msgid="263484519766901593">"Predstavitveni način uporabniškega vmesnika sistema"</string>
@@ -654,8 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satelit, slaba povezava"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelit, dobra povezava"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, povezava je na voljo"</string>
- <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"Povezana s satelitom je vzpostavljena"</string>
- <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"Povezana s satelitom ni vzpostavljena"</string>
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS prek satelita"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Delovni profil"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Zabavno za nekatere, a ne za vse"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Uglaševalnik uporabniškega vmesnika sistema vam omogoča dodatne načine za spreminjanje in prilagajanje uporabniškega vmesnika Android. Te poskusne funkcije lahko v prihodnjih izdajah kadar koli izginejo, se spremenijo ali pokvarijo. Bodite previdni."</string>
@@ -860,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Dodajanje ploščice"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Premik na položaj <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Dodajanje na položaj <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Položaj je neveljaven."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Položaj <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Ploščica je bila dodana"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Ploščica je bila odstranjena"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 068a1a2..b638198 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Kufiri i majtë <xliff:g id="PERCENT">%1$d</xliff:g> për qind"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Kufiri i djathtë <xliff:g id="PERCENT">%1$d</xliff:g> për qind"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Ruajtur në <xliff:g id="APP">%1$s</xliff:g> në profilin e punës"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Ruajtur në <xliff:g id="APP">%1$s</xliff:g> në profilin privat"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Skedarë"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> zbuloi këtë pamje ekrani."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> dhe aplikacionet e tjera të hapura zbuluan këtë pamje ekrani."</string>
@@ -274,7 +275,7 @@
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Ruajtur"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"shkëput"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktivizo"</string>
- <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Aktivizoje automatikisht nesër"</string>
+ <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Aktivizoje automatikisht sërish nesër"</string>
<string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Veçoritë e tilla si \"Ndarja e shpejtë\" dhe \"Gjej pajisjen time\" përdorin Bluetooth-in"</string>
<string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Bluetooth-i do të aktivizohet nesër në mëngjes"</string>
<string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Ndarja e audios"</string>
@@ -457,9 +458,13 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Hiq nga pauza apl. e punës?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Hiq nga pauza"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Mbyll miniaplikacionet në ekranin e kyçjes"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Personalizo miniaplikacionet"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Miniaplikacionet në ekranin e kyçjes"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"zgjidh miniaplikacionin"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Ndërro përdorues"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menyja me tërheqje poshtë"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Të gjitha aplikacionet dhe të dhënat në këtë sesion do të fshihen."</string>
@@ -626,8 +631,10 @@
<string name="volume_panel_collapsed_sliders" msgid="1413383759434791450">"Rrëshqitësit e volumit u palosën"</string>
<string name="volume_panel_hint_mute" msgid="6962563028495243738">"çaktivizo audion: %s"</string>
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"aktivizo audion: %s"</string>
- <string name="media_output_label_title" msgid="872824698593182505">"Po luhet <xliff:g id="LABEL">%s</xliff:g> në"</string>
- <string name="media_output_title_without_playing" msgid="3825663683169305013">"Do të luhet audio në"</string>
+ <string name="media_output_label_title" msgid="872824698593182505">"Po luhet <xliff:g id="LABEL">%s</xliff:g> te"</string>
+ <string name="media_output_title_without_playing" msgid="3825663683169305013">"Do të luhet audio te"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"Sintonizuesi i Sistemit të Ndërfaqes së Përdoruesit"</string>
<string name="status_bar" msgid="4357390266055077437">"Shiriti i statusit"</string>
<string name="demo_mode" msgid="263484519766901593">"Modaliteti i demonstrimit i ndërfaqes së përdoruesit të sistemit"</string>
@@ -655,10 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Sateliti. Lidhje e dobët"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Sateliti. Lidhje e mirë"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Sateliti. Ofrohet lidhje"</string>
- <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
- <skip />
- <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
- <skip />
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS satelitor"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Profili i punës"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Argëtim për disa, por jo për të gjithë!"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Sintonizuesi i Sistemit të Ndërfaqes së Përdoruesit të jep mënyra shtesë për të tërhequr dhe personalizuar ndërfaqen Android të përdoruesit. Këto funksione eksperimentale mund të ndryshojnë, prishen ose zhduken në versionet e ardhshme. Vazhdo me kujdes."</string>
@@ -863,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Shto pllakëzën"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Zhvendos te <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Shto te pozicioni <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Pozicion i pavlefshëm."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Pozicioni <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Pllakëza u shtua"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Pllakëza u hoq"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 0d33e32..4cc1134 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Лева ивица <xliff:g id="PERCENT">%1$d</xliff:g> посто"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Десна ивица <xliff:g id="PERCENT">%1$d</xliff:g> посто"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Сачувано је у апликацији <xliff:g id="APP">%1$s</xliff:g> на пословном профилу"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Сачувано је у апликацији <xliff:g id="APP">%1$s</xliff:g> на приватном профилу"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Фајлови"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"Апликација <xliff:g id="APPNAME">%1$s</xliff:g> је открила овај снимак екрана."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> и друге отворене апликације су откриле овај снимак екрана."</string>
@@ -457,9 +458,13 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Укључити пословне апликације?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Поново активирај"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Затворите виџете на закључаном екрану"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Прилагодите виџете"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Виџети на закључаном екрану"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"изаберите виџет"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Замени корисника"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"падајући мени"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Све апликације и подаци у овој сесији ће бити избрисани."</string>
@@ -628,6 +633,8 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"укључите звук за: %s"</string>
<string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> се пушта на"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"Звук се пушта на"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"Тјунер за кориснички интерфејс система"</string>
<string name="status_bar" msgid="4357390266055077437">"Статусна трака"</string>
<string name="demo_mode" msgid="263484519766901593">"Режим демонстрације за кориснички интерфејс система"</string>
@@ -655,8 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Сателит, веза је лоша"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Сателит, веза је добра"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Сателит, веза је доступна"</string>
- <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"Повезано са сателитом"</string>
- <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"Није повезано са сателитом"</string>
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Хитна помоћ преко сателита"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Пословни профил"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Забава за неке, али не за све"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Тјунер за кориснички интерфејс система вам пружа додатне начине за подешавање и прилагођавање Android корисничког интерфејса. Ове експерименталне функције могу да се промене, откажу или нестану у будућим издањима. Будите опрезни."</string>
@@ -861,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Додајте плочицу"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Преместите на <xliff:g id="POSITION">%1$d</xliff:g>. позицију"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Додајте на <xliff:g id="POSITION">%1$d</xliff:g>. позицију"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Позиција је неважећа."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"<xliff:g id="POSITION">%1$d</xliff:g>. позиција"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Плочица је додата"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Плочица је уклоњена"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 36cf284..b0ce12f 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Vänster gräns: <xliff:g id="PERCENT">%1$d</xliff:g> procent"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Höger gräns: <xliff:g id="PERCENT">%1$d</xliff:g> procent"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Sparad i <xliff:g id="APP">%1$s</xliff:g> i jobbprofilen"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Sparad i <xliff:g id="APP">%1$s</xliff:g> i den privata profilen"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Filer"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> identifierade skärmbilden."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> och andra öppna appar identifierade skärmbilden."</string>
@@ -457,9 +458,13 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Vill du återuppta jobbappar?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Återuppta"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Stäng widgetar på låsskärmen"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Anpassa widgetar"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widgetar på låsskärmen"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"välj widget"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Byt användare"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"rullgardinsmeny"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alla appar och data i denna session kommer att raderas."</string>
@@ -628,6 +633,8 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"slå på ljudet för %s"</string>
<string name="media_output_label_title" msgid="872824698593182505">"Spelar upp <xliff:g id="LABEL">%s</xliff:g> på"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"Ljud spelas upp på"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"Inställningar för systemgränssnitt"</string>
<string name="status_bar" msgid="4357390266055077437">"Statusfält"</string>
<string name="demo_mode" msgid="263484519766901593">"Demoläge för systemgränssnitt"</string>
@@ -655,10 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satellit, dålig anslutning"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellit, bra anslutning"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellit, anslutning tillgänglig"</string>
- <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
- <skip />
- <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
- <skip />
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS-larm via satellit"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Jobbprofil"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Kul för vissa, inte för alla"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Du kan använda inställningarna för systemgränssnitt för att justera användargränssnittet i Android. Dessa experimentfunktioner kan när som helst ändras, sluta fungera eller försvinna. Använd med försiktighet."</string>
@@ -863,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Lägg till ruta"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Flytta till <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Lägg till på position <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Positionen är ogiltig."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Position <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Kortet har lagts till"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Kortet har tagits bort"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 34207f7..8dc22a7 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Mpaka wa sehemu ya kushoto wa asilimia <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Mpaka wa sehemu ya kulia wa asilimia <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Imehifadhiwa kwenye <xliff:g id="APP">%1$s</xliff:g> katika wasifu wa kazini"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Imehifadhiwa kwenye <xliff:g id="APP">%1$s</xliff:g> katika wasifu binafsi"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Faili"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> imetambua picha hii ya skrini."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> na zingine zinazotumika zimetambua picha hii ya skrini."</string>
@@ -457,9 +458,13 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Je, ungependa kuacha kusitisha programu za kazini?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Acha kusitisha"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Funga wijeti kwenye skrini iliyofungwa"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Badilisha wijeti upendavyo"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Wijeti kwenye skrini iliyofungwa"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"chagua wijeti"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Badili mtumiaji"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menyu ya kuvuta chini"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Data na programu zote katika kipindi hiki zitafutwa."</string>
@@ -628,6 +633,8 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"rejesha sauti ya %s"</string>
<string name="media_output_label_title" msgid="872824698593182505">"Inacheza <xliff:g id="LABEL">%s</xliff:g> kwenye"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"Sauti itacheza kwenye"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"Kirekebishi cha kiolesura cha mfumo"</string>
<string name="status_bar" msgid="4357390266055077437">"Sehemu ya kuonyesha hali"</string>
<string name="demo_mode" msgid="263484519766901593">"Hali ya onyesho la kirekebishi cha kiolesura cha mfumo"</string>
@@ -655,8 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Setilaiti, muunganisho hafifu"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Setilaiti, muunganisho thabiti"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Setilaiti, muunganisho unapatikana"</string>
- <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"Umeunganisha kwenye setilaiti"</string>
- <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"Hujaunganisha kwenye setilaiti"</string>
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Msaada kupitia Setilaiti"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Wasifu wa kazini"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Kinafurahisha kwa baadhi ya watu lakini si wote"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Kirekebishi cha kiolesura cha mfumo kinakupa njia zaidi za kugeuza na kubadilisha kiolesura cha Android ili kikufae. Vipengele hivi vya majaribio vinaweza kubadilika, kuharibika au kupotea katika matoleo ya siku zijazo. Endelea kwa uangalifu."</string>
@@ -861,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Ongeza kigae"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Hamishia kwenye <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Ongeza kwenye nafasi ya <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Nafasi si sahihi."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Nafasi ya <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Kigae kimewekwa"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Kigae kimeondolewa"</string>
diff --git a/packages/SystemUI/res/values-sw600dp-land/styles.xml b/packages/SystemUI/res/values-sw600dp-land/styles.xml
index 0d46cbc..cde1a1373 100644
--- a/packages/SystemUI/res/values-sw600dp-land/styles.xml
+++ b/packages/SystemUI/res/values-sw600dp-land/styles.xml
@@ -18,7 +18,7 @@
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
<style name="TextAppearance.AuthNonBioCredential.Title">
- <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
+ <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
<item name="android:layout_marginTop">16dp</item>
<item name="android:textSize">36sp</item>
<item name="android:focusable">true</item>
@@ -26,14 +26,14 @@
</style>
<style name="TextAppearance.AuthNonBioCredential.Subtitle">
- <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
+ <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
<item name="android:layout_marginTop">16dp</item>
<item name="android:textSize">18sp</item>
<item name="android:textColor">?androidprv:attr/materialColorOnSurface</item>
</style>
<style name="TextAppearance.AuthNonBioCredential.Description">
- <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
+ <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
<item name="android:layout_marginTop">16dp</item>
<item name="android:textSize">18sp</item>
<item name="android:textColor">?androidprv:attr/materialColorOnSurface</item>
diff --git a/packages/SystemUI/res/values-sw600dp-port/styles.xml b/packages/SystemUI/res/values-sw600dp-port/styles.xml
index 3add566..85e7af6 100644
--- a/packages/SystemUI/res/values-sw600dp-port/styles.xml
+++ b/packages/SystemUI/res/values-sw600dp-port/styles.xml
@@ -26,7 +26,7 @@
</style>
<style name="TextAppearance.AuthNonBioCredential.Title">
- <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
+ <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
<item name="android:layout_marginTop">24dp</item>
<item name="android:textSize">36sp</item>
<item name="android:focusable">true</item>
diff --git a/packages/SystemUI/res/values-sw720dp-land/styles.xml b/packages/SystemUI/res/values-sw720dp-land/styles.xml
index 7cdd07b..e75173d 100644
--- a/packages/SystemUI/res/values-sw720dp-land/styles.xml
+++ b/packages/SystemUI/res/values-sw720dp-land/styles.xml
@@ -18,7 +18,7 @@
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
<style name="TextAppearance.AuthNonBioCredential.Title">
- <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
+ <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
<item name="android:layout_marginTop">16dp</item>
<item name="android:textSize">36sp</item>
<item name="android:focusable">true</item>
@@ -26,14 +26,14 @@
</style>
<style name="TextAppearance.AuthNonBioCredential.Subtitle">
- <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
+ <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
<item name="android:layout_marginTop">16dp</item>
<item name="android:textSize">18sp</item>
<item name="android:textColor">?androidprv:attr/materialColorOnSurface</item>
</style>
<style name="TextAppearance.AuthNonBioCredential.Description">
- <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
+ <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
<item name="android:layout_marginTop">16dp</item>
<item name="android:textSize">18sp</item>
<item name="android:textColor">?androidprv:attr/materialColorOnSurface</item>
diff --git a/packages/SystemUI/res/values-sw720dp-port/styles.xml b/packages/SystemUI/res/values-sw720dp-port/styles.xml
index 3add566..85e7af6 100644
--- a/packages/SystemUI/res/values-sw720dp-port/styles.xml
+++ b/packages/SystemUI/res/values-sw720dp-port/styles.xml
@@ -26,7 +26,7 @@
</style>
<style name="TextAppearance.AuthNonBioCredential.Title">
- <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
+ <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
<item name="android:layout_marginTop">24dp</item>
<item name="android:textSize">36sp</item>
<item name="android:focusable">true</item>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index 3586172..ee86aca 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"இடது எல்லை <xliff:g id="PERCENT">%1$d</xliff:g> சதவீதம்"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"வலது எல்லை <xliff:g id="PERCENT">%1$d</xliff:g> சதவீதம்"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"பணிக் கணக்கில் உள்ள <xliff:g id="APP">%1$s</xliff:g> ஆப்ஸில் சேமிக்கப்பட்டது"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"தனிப்பட்ட சுயவிவரத்தில் உள்ள <xliff:g id="APP">%1$s</xliff:g> ஆப்ஸில் சேமிக்கப்பட்டது"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Files"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"இந்த ஸ்கிரீன்ஷாட்டை <xliff:g id="APPNAME">%1$s</xliff:g> கண்டறிந்துள்ளது."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"இந்த ஸ்கிரீன்ஷாட்டை <xliff:g id="APPNAME">%1$s</xliff:g> மற்றும் திறந்திருக்கும் பிற ஆப்ஸ் கண்டறிந்துள்ளன."</string>
@@ -457,9 +458,13 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"பணி ஆப்ஸை மீண்டும் இயக்கவா?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"மீண்டும் இயக்கு"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"பூட்டுத் திரையில் விட்ஜெட்களை மூடும்"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"விட்ஜெட்களைப் பிரத்தியேகமாக்கும்"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"பூட்டுத் திரையில் விட்ஜெட்கள்"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"விட்ஜெட்டைத் தேர்ந்தெடுக்கும்"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"பயனரை மாற்று"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"கீழ் இழுக்கும் மெனு"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"இந்த அமர்வின் எல்லா ஆப்ஸும் தரவும் நீக்கப்படும்."</string>
@@ -628,6 +633,8 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"%s ஐ ஒலி இயக்கும்"</string>
<string name="media_output_label_title" msgid="872824698593182505">"இதில் <xliff:g id="LABEL">%s</xliff:g> பிளே ஆகிறது"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"ஆடியோ இதில் பிளே ஆகும்"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"System UI Tuner"</string>
<string name="status_bar" msgid="4357390266055077437">"நிலைப் பட்டி"</string>
<string name="demo_mode" msgid="263484519766901593">"சிஸ்டம் பயனர் இடைமுக டெமோ பயன்முறை"</string>
@@ -655,8 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"சாட்டிலைட், மோசமான இணைப்பு"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"சாட்டிலைட், நிலையான இணைப்பு"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"சாட்டிலைட், இணைப்பு கிடைக்கிறது"</string>
- <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"சாட்டிலைட்டுடன் இணைக்கப்பட்டுள்ளது"</string>
- <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"சாட்டிலைட்டுடன் இணைக்கப்படவில்லை"</string>
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"சாட்டிலைட் SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"பணிக் கணக்கு"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"சில வேடிக்கையாக இருந்தாலும் கவனம் தேவை"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner, Android பயனர் இடைமுகத்தை மாற்றவும் தனிப்பயனாக்கவும் கூடுதல் வழிகளை வழங்குகிறது. இந்தப் பரிசோதனைக்குரிய அம்சங்கள் எதிர்கால வெளியீடுகளில் மாற்றப்படலாம், இடைநிறுத்தப்படலாம் அல்லது தோன்றாமல் போகலாம். கவனத்துடன் தொடரவும்."</string>
@@ -861,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"கட்டத்தைச் சேர்"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g>க்கு நகர்த்தும்"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g>ல் சேர்க்கும்"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"நிலை தவறானது."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"இடம்: <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"கட்டம் சேர்க்கப்பட்டது"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"கட்டம் அகற்றப்பட்டது"</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index 2d76896..d8622a3 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"ఎడమ వైపు సరిహద్దు <xliff:g id="PERCENT">%1$d</xliff:g> శాతం"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"కుడి వైపు సరిహద్దు <xliff:g id="PERCENT">%1$d</xliff:g> శాతం"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"వర్క్ ప్రొఫైల్లోని <xliff:g id="APP">%1$s</xliff:g>లో సేవ్ చేయబడింది"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"ప్రైవేట్ ప్రొఫైల్లోని <xliff:g id="APP">%1$s</xliff:g>లో సేవ్ చేయబడింది"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"ఫైల్స్"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g>, ఈ స్క్రీన్షాట్ను గుర్తించింది."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g>, ఇతర ఓపెన్ యాప్లు ఈ స్క్రీన్షాట్ను గుర్తించాయి."</string>
@@ -271,7 +272,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"బ్లూటూత్ వాడండి"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"కనెక్ట్ అయింది"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"ఆడియో షేరింగ్"</string>
- <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"సేవ్ చేయబడింది"</string>
+ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"సేవ్ అయ్యింది"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"డిస్కనెక్ట్ చేయండి"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"యాక్టివేట్ చేయండి"</string>
<string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"రేపు మళ్లీ ఆటోమేటిక్గా ఆన్ చేస్తుంది"</string>
@@ -368,7 +369,7 @@
<string name="quick_settings_contrast_medium" msgid="5158352575583902566">"మధ్యస్థం"</string>
<string name="quick_settings_contrast_high" msgid="656049259587494499">"అధికం"</string>
<string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"వినికిడి పరికరాలు"</string>
- <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"వినికిడి పరికరం"</string>
+ <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"వినికిడి పరికరాలు"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"కొత్త పరికరాన్ని పెయిర్ చేయండి"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"కొత్త పరికరాన్ని పెయిర్ చేయడానికి క్లిక్ చేయండి"</string>
<string name="hearing_devices_presets_error" msgid="350363093458408536">"ప్రీసెట్ను అప్డేట్ చేయడం సాధ్యపడలేదు"</string>
@@ -459,6 +460,11 @@
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"లాక్ స్క్రీన్లో విడ్జెట్లను మూసివేయండి"</string>
<string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"విడ్జెట్లను అనుకూలంగా మార్చండి"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"లాక్ స్క్రీన్లో విడ్జెట్లు"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"విడ్జెట్ను ఎంచుకోండి"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"వినియోగదారుని మార్చు"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"పుల్డౌన్ మెనూ"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ఈ సెషన్లోని అన్ని యాప్లు మరియు డేటా తొలగించబడతాయి."</string>
@@ -625,8 +631,10 @@
<string name="volume_panel_collapsed_sliders" msgid="1413383759434791450">"వాల్యూమ్ స్లయిడర్లు కుదించబడ్డాయి"</string>
<string name="volume_panel_hint_mute" msgid="6962563028495243738">"%sను మ్యూట్ చేయండి"</string>
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"%sను అన్మ్యూట్ చేయండి"</string>
- <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g>లో ప్లే అవుతోంది"</string>
- <string name="media_output_title_without_playing" msgid="3825663683169305013">"ఆడియో ప్లే అవుతుంది"</string>
+ <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> ప్లే అయ్యే డివైజ్"</string>
+ <string name="media_output_title_without_playing" msgid="3825663683169305013">"ఆడియో ప్లే డివైజ్"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"సిస్టమ్ UI ట్యూనర్"</string>
<string name="status_bar" msgid="4357390266055077437">"స్టేటస్ బార్"</string>
<string name="demo_mode" msgid="263484519766901593">"సిస్టమ్ UI డెమో మోడ్"</string>
@@ -654,8 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"శాటిలైట్, కనెక్షన్ సరిగా లేదు"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"శాటిలైట్, కనెక్షన్ బాగుంది"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"శాటిలైట్, కనెక్షన్ అందుబాటులో ఉంది"</string>
- <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"శాటిలైట్కు కనెక్ట్ చేయబడింది"</string>
- <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"శాటిలైట్కు కనెక్ట్ కాలేదు"</string>
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"ఎమర్జెన్సీ శాటిలైట్ సహాయం"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"ఆఫీస్ ప్రొఫైల్"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"కొందరికి సరదాగా ఉంటుంది కానీ అందరికీ అలాగే ఉండదు"</string>
<string name="tuner_warning" msgid="1861736288458481650">"సిస్టమ్ UI ట్యూనర్ Android వినియోగదారు ఇంటర్ఫేస్ను మెరుగుపరచడానికి మరియు అనుకూలంగా మార్చడానికి మీకు మరిన్ని మార్గాలను అందిస్తుంది. ఈ ప్రయోగాత్మక లక్షణాలు భవిష్యత్తు విడుదలల్లో మార్పుకు లోనవ్వచ్చు, తాత్కాలికంగా లేదా పూర్తిగా నిలిపివేయవచ్చు. జాగ్రత్తగా కొనసాగండి."</string>
@@ -860,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"టైల్ను జోడించండి"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g>కు తరలించండి"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g> స్థానానికి జోడించండి"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"ప్రస్తుత పొజిషన్ చెల్లదు."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"స్థానం <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"టైల్ జోడించబడింది"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"టైల్ తీసివేయబడింది"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 7157e26..9f09b9c 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"ขอบเขตด้านซ้าย <xliff:g id="PERCENT">%1$d</xliff:g> เปอร์เซ็นต์"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"ขอบเขตด้านขวา <xliff:g id="PERCENT">%1$d</xliff:g> เปอร์เซ็นต์"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"บันทึกไว้ที่ <xliff:g id="APP">%1$s</xliff:g> ในโปรไฟล์งาน"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"บันทึกไว้ที่ <xliff:g id="APP">%1$s</xliff:g> ในโปรไฟล์ส่วนตัว"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"ไฟล์"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> ตรวจพบภาพหน้าจอนี้"</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> และแอปอื่นๆ ที่เปิดอยู่ตรวจพบภาพหน้าจอนี้"</string>
@@ -457,9 +458,13 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"ยกเลิกการหยุดแอปงานชั่วคราวไหม"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"ยกเลิกการหยุดชั่วคราว"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"ปิดวิดเจ็ตในหน้าจอล็อก"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"ปรับแต่งวิดเจ็ต"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"วิดเจ็ตในหน้าจอล็อก"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"เลือกวิดเจ็ต"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"สลับผู้ใช้"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"เมนูแบบเลื่อนลง"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ระบบจะลบแอปและข้อมูลทั้งหมดในเซสชันนี้"</string>
@@ -628,6 +633,7 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"เปิดเสียง%s"</string>
<string name="media_output_label_title" msgid="872824698593182505">"กำลังเล่น <xliff:g id="LABEL">%s</xliff:g> ใน"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"เสียงจะเล่นต่อใน"</string>
+ <string name="media_output_title_ongoing_call" msgid="208426888064112006">"กำลังโทรติดต่อ"</string>
<string name="system_ui_tuner" msgid="1471348823289954729">"ตัวรับสัญญาณ UI ระบบ"</string>
<string name="status_bar" msgid="4357390266055077437">"แถบสถานะ"</string>
<string name="demo_mode" msgid="263484519766901593">"โหมดสาธิต UI ของระบบ"</string>
@@ -655,8 +661,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"ดาวเทียม, การเชื่อมต่อไม่ดี"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"ดาวเทียม, การเชื่อมต่อดี"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ดาวเทียม, การเชื่อมต่อที่พร้อมใช้งาน"</string>
- <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"เชื่อมต่อกับดาวเทียมแล้ว"</string>
- <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"ยังไม่ได้เชื่อมต่อกับดาวเทียม"</string>
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS ดาวเทียม"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"โปรไฟล์งาน"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"เพลิดเพลินกับบางส่วนแต่ไม่ใช่ทั้งหมด"</string>
<string name="tuner_warning" msgid="1861736288458481650">"ตัวรับสัญญาณ UI ระบบช่วยให้คุณมีวิธีพิเศษในการปรับแต่งและกำหนดค่าส่วนติดต่อผู้ใช้ Android ฟีเจอร์รุ่นทดลองเหล่านี้อาจมีการเปลี่ยนแปลง ขัดข้อง หรือหายไปในเวอร์ชันอนาคต โปรดดำเนินการด้วยความระมัดระวัง"</string>
@@ -861,6 +866,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"เพิ่มชิ้นส่วน"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"ย้ายไปที่ <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"เพิ่มไปยังตำแหน่ง <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"ตำแหน่งไม่ถูกต้อง"</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"ตำแหน่ง <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"เพิ่มชิ้นส่วนแล้ว"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"นำชิ้นส่วนออกแล้ว"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 51782a3..9122627 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"<xliff:g id="PERCENT">%1$d</xliff:g> (na) porsyento sa hangganan sa kaliwa"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"<xliff:g id="PERCENT">%1$d</xliff:g> (na) porsyento sa hangganan sa kanan"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Na-save sa <xliff:g id="APP">%1$s</xliff:g> sa profile sa trabaho"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Naka-save sa <xliff:g id="APP">%1$s</xliff:g> sa pribadong profile"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Mga File"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"Na-detect ng <xliff:g id="APPNAME">%1$s</xliff:g> ang screenshot. na ito"</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"Na-detect ng <xliff:g id="APPNAME">%1$s</xliff:g> at ng iba pang bukas na app ang screenshot na ito."</string>
@@ -457,9 +458,13 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"I-unpause ang mga work app?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"I-unpause"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Isara ang mga widget sa lock screen"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"I-customize ang mga widget"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Mga widget sa lock screen"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"pumili ng widget"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Magpalit ng user"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"pulldown menu"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Ide-delete ang lahat ng app at data sa session na ito."</string>
@@ -628,6 +633,7 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"i-unmute ang %s"</string>
<string name="media_output_label_title" msgid="872824698593182505">"Nagpe-play ang <xliff:g id="LABEL">%s</xliff:g> sa"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"I-play ang audio sa"</string>
+ <string name="media_output_title_ongoing_call" msgid="208426888064112006">"Tumatawag sa"</string>
<string name="system_ui_tuner" msgid="1471348823289954729">"Tuner ng System UI"</string>
<string name="status_bar" msgid="4357390266055077437">"Status bar"</string>
<string name="demo_mode" msgid="263484519766901593">"Demo mode ng System UI"</string>
@@ -655,10 +661,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satellite, mahina ang koneksyon"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellite, malakas ang koneksyon"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellite, may koneksyon"</string>
- <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
- <skip />
- <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
- <skip />
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satellite SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Profile sa trabaho"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Masaya para sa ilan ngunit hindi para sa lahat"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Nagbibigay sa iyo ang Tuner ng System UI ng mga karagdagang paraan upang baguhin at i-customize ang user interface ng Android. Ang mga pang-eksperimentong feature na ito ay maaaring magbago, masira o mawala sa mga pagpapalabas sa hinaharap. Magpatuloy nang may pag-iingat."</string>
@@ -863,6 +866,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Magdagdag ng tile"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Ilipat sa <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Idagdag sa posisyong <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Invalid ang posisyon."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Posisyon <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Idinagdag ang tile"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Inalis ang tile"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index bf85818..1f7a8e0 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Sol sınır yüzde <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Sağ sınır yüzde <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"İş profilinde <xliff:g id="APP">%1$s</xliff:g> uygulamasına kaydedildi"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Gizli profilde <xliff:g id="APP">%1$s</xliff:g> uygulamasına kaydedildi"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Dosyalar"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> bu ekran görüntüsünü algıladı."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> ve diğer açık uygulamalar bu ekran görüntüsünü algıladı."</string>
@@ -457,9 +458,13 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"İş uygulamaları devam ettirilsin mi?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Devam ettir"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Kilit ekranındaki widget\'ları kapat"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Widget\'ları özelleştir"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Kilit ekranındaki widget\'lar"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"widget seçin"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Kullanıcı değiştirme"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"açılır menü"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Bu oturumdaki tüm uygulamalar ve veriler silinecek."</string>
@@ -591,14 +596,14 @@
<string name="screen_pinning_exit" msgid="4553787518387346893">"Uygulamanın sabitlemesi kaldırıldı"</string>
<string name="stream_voice_call" msgid="7468348170702375660">"Çağrı"</string>
<string name="stream_system" msgid="7663148785370565134">"Sistem"</string>
- <string name="stream_ring" msgid="7550670036738697526">"Zili çaldır"</string>
+ <string name="stream_ring" msgid="7550670036738697526">"Zil"</string>
<string name="stream_music" msgid="2188224742361847580">"Medya"</string>
<string name="stream_alarm" msgid="16058075093011694">"Alarm"</string>
<string name="stream_notification" msgid="7930294049046243939">"Bildirim"</string>
<string name="stream_bluetooth_sco" msgid="6234562365528664331">"Bluetooth"</string>
<string name="stream_dtmf" msgid="7322536356554673067">"Çift ton çoklu frekans"</string>
<string name="stream_accessibility" msgid="3873610336741987152">"Erişilebilirlik"</string>
- <string name="volume_ringer_status_normal" msgid="1339039682222461143">"Zili çaldır"</string>
+ <string name="volume_ringer_status_normal" msgid="1339039682222461143">"Zil"</string>
<string name="volume_ringer_status_vibrate" msgid="6970078708957857825">"Titreşim"</string>
<string name="volume_ringer_status_silent" msgid="3691324657849880883">"Sesi kapat"</string>
<string name="media_device_cast" msgid="4786241789687569892">"Yayınla"</string>
@@ -628,6 +633,8 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"%s sesini açma"</string>
<string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> şurada çalacak:"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"Ses şurada çalacak:"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"Sistem Arayüzü Ayarlayıcısı"</string>
<string name="status_bar" msgid="4357390266055077437">"Durum çubuğu"</string>
<string name="demo_mode" msgid="263484519766901593">"Sistem kullanıcı arayüzü demo modu"</string>
@@ -655,10 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Uydu, bağlantı zayıf"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Uydu, bağlantı güçlü"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Uydu, bağlantı mevcut"</string>
- <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
- <skip />
- <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
- <skip />
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Acil Uydu Bağlantısı"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"İş profili"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Bazıları için eğlenceliyken diğerleri için olmayabilir"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Sistem Kullanıcı Arayüzü Ayarlayıcı, Android kullanıcı arayüzünde değişiklikler yapmanız ve arayüzü özelleştirmeniz için ekstra yollar sağlar. Bu deneysel özellikler değişebilir, bozulabilir veya gelecekteki sürümlerde yer almayabilir. Dikkatli bir şekilde devam edin."</string>
@@ -863,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Kutu ekle"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g> konumuna taşı"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g> konumuna ekle"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Konum geçersiz."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Konum: <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Kutu eklendi"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Kutu kaldırıldı"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 71f1fb6..e9b45bf 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Зліва на <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Справа на <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Збережено в додатку <xliff:g id="APP">%1$s</xliff:g> у робочому профілі"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Збережено в додатку <xliff:g id="APP">%1$s</xliff:g> в особистому профілі"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Файли"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"Додаток <xliff:g id="APPNAME">%1$s</xliff:g> виявив цей знімок екрана."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> та інші відкриті додатки виявили цей знімок екрана."</string>
@@ -457,9 +458,13 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Увімкнути робочі додатки?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Увімкнути"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Закрити віджети на заблокованому екрані"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Налаштувати віджети"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Віджети на заблокованому екрані"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"виберіть віджет"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Змінити користувача"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"спадне меню"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Усі додатки й дані з цього сеансу буде видалено."</string>
@@ -626,8 +631,10 @@
<string name="volume_panel_collapsed_sliders" msgid="1413383759434791450">"Повзунки гучності згорнуто"</string>
<string name="volume_panel_hint_mute" msgid="6962563028495243738">"вимкнути звук %s"</string>
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"увімкнути звук %s"</string>
- <string name="media_output_label_title" msgid="872824698593182505">"Відтворюється <xliff:g id="LABEL">%s</xliff:g> на:"</string>
- <string name="media_output_title_without_playing" msgid="3825663683169305013">"Аудіо гратиме на:"</string>
+ <string name="media_output_label_title" msgid="872824698593182505">"Де відтворюється <xliff:g id="LABEL">%s</xliff:g>:"</string>
+ <string name="media_output_title_without_playing" msgid="3825663683169305013">"Де гратиме аудіо:"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"System UI Tuner"</string>
<string name="status_bar" msgid="4357390266055077437">"Рядок стану"</string>
<string name="demo_mode" msgid="263484519766901593">"Демо-режим інтерфейсу системи"</string>
@@ -655,10 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Погане з’єднання із супутником"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Хороше з’єднання із супутником"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Доступне з’єднання із супутником"</string>
- <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
- <skip />
- <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
- <skip />
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Супутниковий сигнал SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Робочий профіль"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Це цікаво, але будьте обачні"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner пропонує нові способи налаштувати та персоналізувати інтерфейс користувача Android. Ці експериментальні функції можуть змінюватися, не працювати чи зникати в майбутніх версіях. Будьте обачні."</string>
@@ -863,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Додати панель"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Перемістити на позицію <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Додати на позицію <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Позиція недійсна."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Позиція <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Опцію додано"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Опцію вилучено"</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 0b79b1c..f9fc9f0 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"بایاں احاطہ <xliff:g id="PERCENT">%1$d</xliff:g> فیصد"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"دایاں احاطہ <xliff:g id="PERCENT">%1$d</xliff:g> فیصد"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"دفتری پروفائل میں <xliff:g id="APP">%1$s</xliff:g> میں محفوظ کی گئی"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"نجی پروفائل میں <xliff:g id="APP">%1$s</xliff:g> میں محفوظ کیا گیا"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"فائلز"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> نے اس اسکرین شاٹ کا پتا لگایا۔"</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> اور دیگر کھلی ایپس نے اس اسکرین شاٹ کا پتا لگایا۔"</string>
@@ -459,6 +460,11 @@
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"مقفل اسکرین پر ویجٹس بند کریں"</string>
<string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"ویجیٹس کو حسب ضرورت بنائیں"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"مقفل اسکرین پر ویجیٹس"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"ویجیٹ منتخب کریں"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"صارف سوئچ کریں"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"پل ڈاؤن مینیو"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"اس سیشن میں موجود سبھی ایپس اور ڈیٹا کو حذف کر دیا جائے گا۔"</string>
@@ -627,6 +633,8 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"%s غیر خاموش کریں"</string>
<string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> پر چل رہی ہے"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"آڈیو اس پر چلے گی"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"سسٹم UI ٹیونر"</string>
<string name="status_bar" msgid="4357390266055077437">"اسٹیٹس بار"</string>
<string name="demo_mode" msgid="263484519766901593">"سسٹم UI ڈیمو موڈ"</string>
@@ -654,10 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"سیٹلائٹ، کنکشن خراب ہے"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"سیٹلائٹ، کنکشن اچھا ہے"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"سیٹلائٹ، کنکشن دستیاب ہے"</string>
- <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
- <skip />
- <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
- <skip />
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"سیٹلائٹ SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"دفتری پروفائل"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"کچھ کیلئے دلچسپ لیکن سبھی کیلئے نہیں"</string>
<string name="tuner_warning" msgid="1861736288458481650">"سسٹم UI ٹیونر Android صارف انٹر فیس میں ردوبدل کرنے اور اسے حسب ضرورت بنانے کیلئے آپ کو اضافی طریقے دیتا ہے۔ یہ تجرباتی خصوصیات مستقبل کی ریلیزز میں تبدیل ہو سکتی، رک سکتی یا غائب ہو سکتی ہیں۔ احتیاط کے ساتھ آگے بڑھیں۔"</string>
@@ -862,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"ٹائل شامل کریں"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g> میں منتقل کریں"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"پوزیشن <xliff:g id="POSITION">%1$d</xliff:g> میں شامل کریں"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"پوزیشن غلط ہے۔"</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"پوزیشن <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"ٹائل کو شامل کیا گیا"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"ٹائل کو ہٹا دیا گیا"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 78def5d..60baeec 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Chap chegara <xliff:g id="PERCENT">%1$d</xliff:g> foiz"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Oʻng chegara <xliff:g id="PERCENT">%1$d</xliff:g> foiz"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Ish profilidagi <xliff:g id="APP">%1$s</xliff:g> ilovasiga saqlandi"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Yopiq profildagi <xliff:g id="APP">%1$s</xliff:g> ilovasiga saqlandi"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Fayllar"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> skrinshot olinganini aniqladi."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> va boshqa ochiq ilovalar skrinshot olinganini aniqladi."</string>
@@ -457,9 +458,13 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Ishga oid ilovalar qaytarilsinmi?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Davom ettirish"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Ekran qulfida vidjetlarni yopish"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Vidjetlarni moslash"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Ekran qulfidagi vidjetlar"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"vidjet tanlash"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Foydalanuvchini almashtirish"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"tortib tushiriladigan menyu"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Ushbu seansdagi barcha ilovalar va ma’lumotlar o‘chirib tashlanadi."</string>
@@ -628,6 +633,7 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"%s ovozini chiqarish"</string>
<string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g>da ijro etilmoqda"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"Audio ijro etiladi"</string>
+ <string name="media_output_title_ongoing_call" msgid="208426888064112006">"Chaqiruv yoniq"</string>
<string name="system_ui_tuner" msgid="1471348823289954729">"SystemUI Tuner"</string>
<string name="status_bar" msgid="4357390266055077437">"Holat qatori"</string>
<string name="demo_mode" msgid="263484519766901593">"Tizim interfeysi demo rejimi"</string>
@@ -655,8 +661,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Sputnik, aloqa sifati past"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Sputnik, aloqa sifati yaxshi"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Sputnik, aloqa mavjud"</string>
- <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"Sputnikka ulangan"</string>
- <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"Sputnikka ulanmagan"</string>
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Sputnik SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Ish profili"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Diqqat!"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner yordamida siz Android foydalanuvchi interfeysini tuzatish va o‘zingizga moslashtirishingiz mumkin. Ushbu tajribaviy funksiyalar o‘zgarishi, buzilishi yoki keyingi versiyalarda olib tashlanishi mumkin. Ehtiyot bo‘lib davom eting."</string>
@@ -861,6 +866,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Katakcha kiritish"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Bu joyga olish: <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Bu joyga kiritish: <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Pozitsiya yaroqsiz."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Joylashuv: <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Katakcha kiritildi"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Katakcha olib tashlandi"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index e50dd2f..9656eb3 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Cạnh trái <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Cạnh phải <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Đã lưu vào <xliff:g id="APP">%1$s</xliff:g> trong hồ sơ công việc"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Đã lưu vào <xliff:g id="APP">%1$s</xliff:g> trong hồ sơ riêng tư"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Files"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> đã phát hiện thấy ảnh chụp màn hình này."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> và các ứng dụng đang mở khác đã phát hiện thấy ảnh chụp màn hình này."</string>
@@ -457,9 +458,13 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Tiếp tục dùng ứng dụng công việc?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Tiếp tục dùng"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Đóng các tiện ích trên màn hình khoá"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Tuỳ chỉnh tiện ích"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Các tiện ích trên màn hình khoá"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"chọn tiện ích"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Chuyển đổi người dùng"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"trình đơn kéo xuống"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Tất cả ứng dụng và dữ liệu trong phiên này sẽ bị xóa."</string>
@@ -628,6 +633,8 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"bật tiếng %s"</string>
<string name="media_output_label_title" msgid="872824698593182505">"Đang phát <xliff:g id="LABEL">%s</xliff:g> trên"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"Âm thanh sẽ phát trên"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"Bộ điều hướng giao diện người dùng hệ thống"</string>
<string name="status_bar" msgid="4357390266055077437">"Thanh trạng thái"</string>
<string name="demo_mode" msgid="263484519766901593">"Chế độ thử nghiệm giao diện người dùng hệ thống"</string>
@@ -655,10 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Kết nối vệ tinh kém"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Kết nối vệ tinh tốt"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Hiện có kết nối vệ tinh"</string>
- <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
- <skip />
- <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
- <skip />
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Liên lạc khẩn cấp qua vệ tinh"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Hồ sơ công việc"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Thú vị đối với một số người nhưng không phải tất cả"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Bộ điều hướng giao diện người dùng hệ thống cung cấp thêm cho bạn những cách chỉnh sửa và tùy chỉnh giao diện người dùng Android. Những tính năng thử nghiệm này có thể thay đổi, hỏng hoặc biến mất trong các phiên bản tương lai. Hãy thận trọng khi tiếp tục."</string>
@@ -863,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Thêm ô"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Di chuyển tới <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Thêm vào vị trí <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Vị trí không hợp lệ."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Vị trí <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Đã thêm thẻ thông tin"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Đã xóa thẻ thông tin"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index b0740a5..6f1a0bd0 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"左侧边界百分之 <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"右侧边界百分之 <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"已保存到工作资料名下的 <xliff:g id="APP">%1$s</xliff:g>中"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"已保存在私密个人资料中的<xliff:g id="APP">%1$s</xliff:g>内"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"文件"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> 检测到此屏幕截图。"</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> 及其他打开的应用检测到此屏幕截图。"</string>
@@ -457,9 +458,13 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"是否为工作应用解除暂停状态?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"解除暂停"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"关闭锁定屏幕上的微件"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"自定义微件"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"锁定屏幕上的微件"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"选择微件"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"切换用户"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"下拉菜单"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"此会话中的所有应用和数据都将被删除。"</string>
@@ -628,6 +633,8 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"取消静音“%s”"</string>
<string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g>播放位置:"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"音频播放位置:"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"系统界面调节工具"</string>
<string name="status_bar" msgid="4357390266055077437">"状态栏"</string>
<string name="demo_mode" msgid="263484519766901593">"系统界面演示模式"</string>
@@ -655,8 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"卫星,连接质量不佳"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"卫星,连接质量良好"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"卫星,可连接"</string>
- <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"已连接到卫星"</string>
- <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"未连接到卫星"</string>
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"卫星紧急呼救"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"工作资料"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"并不适合所有用户"</string>
<string name="tuner_warning" msgid="1861736288458481650">"系统界面调节工具可让您以更多方式调整及定制 Android 界面。在日后推出的版本中,这些实验性功能可能会变更、失效或消失。操作时请务必谨慎。"</string>
@@ -861,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"添加功能块"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"移至 <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"添加到位置 <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"位置无效。"</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"位置 <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"已添加功能块"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"已移除功能块"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 94dd480..47d0692 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"左方邊界 <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"右方邊界 <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"已儲存在工作設定檔的「<xliff:g id="APP">%1$s</xliff:g>」中"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"已儲存在私人設定檔的「<xliff:g id="APP">%1$s</xliff:g>」中"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"檔案"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> 偵測到此螢幕截圖。"</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> 和其他開啟的應用程式偵測到此螢幕截圖。"</string>
@@ -459,6 +460,11 @@
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"關閉上鎖畫面上的小工具"</string>
<string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"自訂小工具"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"上鎖畫面上的小工具"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"揀小工具"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"切換使用者"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"下拉式選單"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"這個工作階段中的所有應用程式和資料都會被刪除。"</string>
@@ -627,6 +633,8 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"取消%s的靜音設定"</string>
<string name="media_output_label_title" msgid="872824698593182505">"正在播放「<xliff:g id="LABEL">%s</xliff:g>」的裝置:"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"音訊播放媒體"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"系統使用者介面調諧器"</string>
<string name="status_bar" msgid="4357390266055077437">"狀態列"</string>
<string name="demo_mode" msgid="263484519766901593">"系統使用者介面示範模式"</string>
@@ -654,8 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"衛星,連線質素唔好"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"衛星,連線質素好"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"衛星,可以連線"</string>
- <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"已連上衛星"</string>
- <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"未連上衛星"</string>
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"緊急衛星連接"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"工作設定檔"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"這只是測試版本,並不包含完整功能"</string>
<string name="tuner_warning" msgid="1861736288458481650">"使用者介面調諧器讓你以更多方法修改和自訂 Android 使用者介面。但請小心,這些實驗功能可能會在日後發佈時更改、分拆或消失。"</string>
@@ -860,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"加圖塊"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"移去 <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"加去位置 <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"位置冇效。"</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"位置 <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"加咗圖塊"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"移除咗圖塊"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index d072c77..b3ed7a0 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"左側邊界百分之 <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"右側邊界百分之 <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"已儲存在工作資料夾的「<xliff:g id="APP">%1$s</xliff:g>」中"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"已儲存在個人資料夾的「<xliff:g id="APP">%1$s</xliff:g>」"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"檔案"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"「<xliff:g id="APPNAME">%1$s</xliff:g>」偵測到這張螢幕截圖。"</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"「<xliff:g id="APPNAME">%1$s</xliff:g>」和其他開啟的應用程式偵測到這張螢幕截圖。"</string>
@@ -459,6 +460,11 @@
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"關閉螢幕鎖定畫面上的小工具"</string>
<string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"自訂小工具"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"螢幕鎖定畫面上的小工具"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"選取小工具"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"切換使用者"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"下拉式選單"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"這個工作階段中的所有應用程式和資料都會刪除。"</string>
@@ -627,6 +633,8 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"將%s取消靜音"</string>
<string name="media_output_label_title" msgid="872824698593182505">"正在播放「<xliff:g id="LABEL">%s</xliff:g>」的裝置:"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"音訊播放位置"</string>
+ <!-- no translation found for media_output_title_ongoing_call (208426888064112006) -->
+ <skip />
<string name="system_ui_tuner" msgid="1471348823289954729">"系統使用者介面調整精靈"</string>
<string name="status_bar" msgid="4357390266055077437">"狀態列"</string>
<string name="demo_mode" msgid="263484519766901593">"系統 UI 展示模式"</string>
@@ -654,8 +662,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"衛星,連線品質不佳"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"衛星,連線品質良好"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"衛星,可連線"</string>
- <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"已連上衛星"</string>
- <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"未連上衛星"</string>
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"緊急衛星連線"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"工作資料夾"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"有趣與否,見仁見智"</string>
<string name="tuner_warning" msgid="1861736288458481650">"系統使用者介面調整精靈可讓你透過其他方式,調整及自訂 Android 使用者介面。這些實驗性功能隨著版本更新可能會變更、損壞或消失,執行時請務必謹慎。"</string>
@@ -860,6 +867,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"新增圖塊"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"移至 <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"新增到位置 <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"位置無效。"</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"位置 <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"已新增設定方塊"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"已移除設定方塊"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 6c746d3..6e9e08b 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -97,6 +97,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Iphesenti elingu-<xliff:g id="PERCENT">%1$d</xliff:g> lomngcele ongakwesobunxele"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Iphesenti elingu-<xliff:g id="PERCENT">%1$d</xliff:g> lomngcele ongakwesokudla"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Kulondolozwe ku-<xliff:g id="APP">%1$s</xliff:g> kuphrofayela yomsebenzi"</string>
+ <string name="screenshot_private_profile_notification" msgid="1704440899154243171">"Kulondolozwe kokuthi <xliff:g id="APP">%1$s</xliff:g> ephrofayeleni egodliwe"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Amafayela"</string>
<string name="screenshot_detected_template" msgid="7940376642921719915">"I-<xliff:g id="APPNAME">%1$s</xliff:g> ithole lesi sithombe-skrini."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"I-<xliff:g id="APPNAME">%1$s</xliff:g> namanye ama-app avuliwe athole lesi sithombe-skrini."</string>
@@ -459,6 +460,11 @@
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Vala amawijethi ekukhiyeni isikrini"</string>
<string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Yenza ngokwezifiso amawijethi"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Amawijethi ekukhiyeni isikrini"</string>
+ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"khetha iwijethi"</string>
+ <!-- no translation found for accessibility_action_label_remove_widget (3373779447448758070) -->
+ <skip />
+ <!-- no translation found for accessibility_action_label_place_widget (1914197458644168978) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Shintsha umsebenzisi"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"imenyu yokudonsela phansi"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Wonke ama-app nedatha kulesi sikhathi azosuswa."</string>
@@ -627,6 +633,7 @@
<string name="volume_panel_hint_unmute" msgid="7489063242934477382">"susa ukuthula kwe-%s"</string>
<string name="media_output_label_title" msgid="872824698593182505">"Idlala ku-<xliff:g id="LABEL">%s</xliff:g>"</string>
<string name="media_output_title_without_playing" msgid="3825663683169305013">"Umsindo uzodlala"</string>
+ <string name="media_output_title_ongoing_call" msgid="208426888064112006">"Ifonela kokuthi"</string>
<string name="system_ui_tuner" msgid="1471348823289954729">"Isishuni se-UI yesistimu"</string>
<string name="status_bar" msgid="4357390266055077437">"Ibha yesimo"</string>
<string name="demo_mode" msgid="263484519766901593">"Imodi yedemo ye-UI yesistimu"</string>
@@ -654,8 +661,7 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Isathelayithi, uxhumano olungalungile"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Isethelayithi, uxhumano oluhle"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Isethelayithi, uxhumano luyatholakala"</string>
- <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"Ixhunywe esethelayithini"</string>
- <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"Ayixhunyiwe esethelayithini"</string>
+ <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Isethelayithi yokuxhumana ngezimo eziphuthumayo"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Iphrofayela yomsebenzi"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Kuyajabulisa kwabanye kodwa hhayi bonke"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Isishuni se-UI sesistimu sikunika izindlela ezingeziwe zokuhlobisa nokwenza ngezifiso isixhumanisi sokubona se-Android. Lezi zici zesilingo zingashintsha, zephuke, noma zinyamalale ekukhishweni kwangakusasa. Qhubeka ngokuqaphela."</string>
@@ -860,6 +866,7 @@
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Engeza ithayela"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Hambisa ku-<xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Engeza kusikhundla se-<xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Indawo ayivumelekile."</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Isikhundla se-<xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Ithayela lingeziwe"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Ithayela likhishiwe"</string>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 6bfd088..2ba72e3 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -635,9 +635,13 @@
58.0001 29.2229,56.9551 26.8945,55.195
</string>
- <!-- The time (in ms) needed to trigger the lock icon view's long-press affordance -->
+ <!-- The time (in ms) needed to trigger the device entry icon view's long-press affordance -->
<integer name="config_lockIconLongPress" translatable="false">200</integer>
+ <!-- The time (in ms) needed to trigger the device entry icon view's long-press affordance
+ when the device supports an under-display fingerprint sensor -->
+ <integer name="config_udfpsDeviceEntryIconLongPress" translatable="false">100</integer>
+
<!-- package name of a built-in camera app to use to restrict implicit intent resolution
when the double-press power gesture is used. Ignored if empty. -->
<string translatable="false" name="config_cameraGesturePackage"></string>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index a7a6d5b..a1daebd 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -430,6 +430,7 @@
<dimen name="overlay_button_corner_radius">16dp</dimen>
<!-- Margin between successive chips -->
<dimen name="overlay_action_chip_margin_start">8dp</dimen>
+ <dimen name="shelf_action_chip_margin_start">12dp</dimen>
<dimen name="overlay_action_chip_padding_vertical">12dp</dimen>
<dimen name="overlay_action_chip_icon_size">24sp</dimen>
<!-- Padding on each side of the icon for icon-only chips -->
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 40d863d..45bcd82 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1186,6 +1186,10 @@
<string name="accessibility_content_description_for_communal_hub">Widgets on lock screen</string>
<!-- Label for accessibility action to select a widget in edit mode. [CHAR LIMIT=NONE] -->
<string name="accessibility_action_label_select_widget">select widget</string>
+ <!-- Label for accessibility action to remove a widget in edit mode. [CHAR LIMIT=NONE] -->
+ <string name="accessibility_action_label_remove_widget">remove widget</string>
+ <!-- Label for accessibility action to place a widget in edit mode after selecting move widget. [CHAR LIMIT=NONE] -->
+ <string name="accessibility_action_label_place_widget">place selected widget</string>
<!-- Related to user switcher --><skip/>
@@ -1634,12 +1638,15 @@
<!-- Hint for accessibility. A stream name is a parameter. For example: double tap to unmute media [CHAR_LIMIT=NONE] -->
<string name="volume_panel_hint_unmute">unmute %s</string>
- <!-- Title with application label for media output settings. [CHAR LIMIT=20] -->
+ <!-- Title with application label for media output settings when there is media playing. [CHAR LIMIT=20] -->
<string name="media_output_label_title">Playing <xliff:g id="label" example="Music Player">%s</xliff:g> on</string>
<!-- Title for media output settings without media is playing. [CHAR LIMIT=20] -->
<string name="media_output_title_without_playing">Audio will play on</string>
+ <!-- Title for media output settings when there is an ongoing call in progress. [CHAR LIMIT=20] -->
+ <string name="media_output_title_ongoing_call">Calling on</string>
+
<!-- Name of special SystemUI debug settings -->
<string name="system_ui_tuner">System UI Tuner</string>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 69de45e..2c4cdb9 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -175,21 +175,21 @@
</style>
<style name="TextAppearance.AuthCredential.OldTitle">
- <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
+ <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
<item name="android:paddingTop">12dp</item>
<item name="android:paddingHorizontal">24dp</item>
<item name="android:textSize">24sp</item>
</style>
<style name="TextAppearance.AuthCredential.OldSubtitle">
- <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
+ <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
<item name="android:paddingTop">8dp</item>
<item name="android:paddingHorizontal">24dp</item>
<item name="android:textSize">16sp</item>
</style>
<style name="TextAppearance.AuthCredential.OldDescription">
- <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
+ <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
<item name="android:paddingTop">8dp</item>
<item name="android:paddingHorizontal">24dp</item>
<item name="android:textSize">14sp</item>
@@ -205,7 +205,7 @@
</style>
<style name="TextAppearance.AuthCredential.Title" parent="TextAppearance.Material3.HeadlineSmall" >
- <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
+ <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
<item name="android:textColor">?androidprv:attr/materialColorOnSurface</item>
</style>
@@ -257,7 +257,7 @@
</style>
<style name="TextAppearance.AuthNonBioCredential.Title">
- <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
+ <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
<item name="android:layout_marginTop">24dp</item>
<item name="android:textSize">36dp</item>
<item name="android:focusable">true</item>
@@ -265,14 +265,14 @@
</style>
<style name="TextAppearance.AuthNonBioCredential.Subtitle">
- <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
+ <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
<item name="android:layout_marginTop">20dp</item>
<item name="android:textSize">18sp</item>
<item name="android:textColor">?androidprv:attr/materialColorOnSurface</item>
</style>
<style name="TextAppearance.AuthNonBioCredential.Description">
- <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
+ <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
<item name="android:layout_marginTop">20dp</item>
<item name="android:textSize">18sp</item>
<item name="android:textColor">?androidprv:attr/materialColorOnSurface</item>
diff --git a/packages/SystemUI/shared/keyguard/src/com/android/keyguard/BasePasswordTextView.java b/packages/SystemUI/shared/keyguard/src/com/android/keyguard/BasePasswordTextView.java
index fe12134..863f0c3 100644
--- a/packages/SystemUI/shared/keyguard/src/com/android/keyguard/BasePasswordTextView.java
+++ b/packages/SystemUI/shared/keyguard/src/com/android/keyguard/BasePasswordTextView.java
@@ -231,7 +231,7 @@
info.setClassName(EditText.class.getName());
info.setPassword(true);
info.setText(getTransformedText());
-
+ info.setSelected(false);
info.setEditable(true);
info.setInputType(InputType.TYPE_NUMBER_VARIATION_PASSWORD);
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java
index 6e1b670..660f0db 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java
@@ -68,6 +68,7 @@
import java.io.PrintWriter;
import java.util.Optional;
import java.util.concurrent.Executor;
+import java.util.concurrent.ThreadPoolExecutor;
import java.util.function.Supplier;
/**
@@ -199,6 +200,10 @@
return mContext;
}
+ /**
+ * We should pass single threaded executor (rather than {@link ThreadPoolExecutor}) as we will
+ * make binder calls on that executor and ordering is vital.
+ */
public void setBgExecutor(Executor bgExecutor) {
mBgExecutor = bgExecutor;
}
@@ -230,25 +235,22 @@
mListenersRegistered = true;
mBgExecutor.execute(() -> {
+ if (registerRotationWatcher) {
+ try {
+ WindowManagerGlobal.getWindowManagerService()
+ .watchRotation(mRotationWatcher, DEFAULT_DISPLAY);
+ mRotationWatcherRegistered = true;
+ } catch (IllegalArgumentException e) {
+ Log.w(TAG, "RegisterListeners for the display failed", e);
+ } catch (RemoteException e) {
+ Log.e(TAG, "RegisterListeners caught a RemoteException", e);
+ }
+ }
final Intent intent = mContext.registerReceiver(mDockedReceiver,
new IntentFilter(Intent.ACTION_DOCK_EVENT));
mContext.getMainExecutor().execute(() -> updateDockedState(intent));
});
- if (registerRotationWatcher) {
- try {
- WindowManagerGlobal.getWindowManagerService()
- .watchRotation(mRotationWatcher, DEFAULT_DISPLAY);
- mRotationWatcherRegistered = true;
- } catch (IllegalArgumentException e) {
- mListenersRegistered = false;
- Log.w(TAG, "RegisterListeners for the display failed", e);
- } catch (RemoteException e) {
- Log.e(TAG, "RegisterListeners caught a RemoteException", e);
- return;
- }
- }
-
TaskStackChangeListeners.getInstance().registerTaskStackListener(mTaskStackListener);
}
@@ -265,17 +267,16 @@
} catch (IllegalArgumentException e) {
Log.e(TAG, "Docked receiver already unregistered", e);
}
- });
- if (mRotationWatcherRegistered) {
- try {
- WindowManagerGlobal.getWindowManagerService().removeRotationWatcher(
- mRotationWatcher);
- } catch (RemoteException e) {
- Log.e(TAG, "UnregisterListeners caught a RemoteException", e);
- return;
+ if (mRotationWatcherRegistered) {
+ try {
+ WindowManagerGlobal.getWindowManagerService().removeRotationWatcher(
+ mRotationWatcher);
+ } catch (RemoteException e) {
+ Log.e(TAG, "UnregisterListeners caught a RemoteException", e);
+ }
}
- }
+ });
TaskStackChangeListeners.getInstance().unregisterTaskStackListener(mTaskStackListener);
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
index c08b083..69aa909 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
@@ -77,7 +77,7 @@
// settings is expanded.
public static final int SYSUI_STATE_QUICK_SETTINGS_EXPANDED = 1 << 11;
// Winscope tracing is enabled
- public static final int SYSUI_STATE_TRACING_ENABLED = 1 << 12;
+ public static final int SYSUI_STATE_DISABLE_GESTURE_SPLIT_INVOCATION = 1 << 12;
// The Assistant gesture should be constrained. It is up to the launcher implementation to
// decide how to constrain it
public static final int SYSUI_STATE_ASSIST_GESTURE_CONSTRAINED = 1 << 13;
@@ -148,7 +148,7 @@
SYSUI_STATE_OVERVIEW_DISABLED,
SYSUI_STATE_HOME_DISABLED,
SYSUI_STATE_SEARCH_DISABLED,
- SYSUI_STATE_TRACING_ENABLED,
+ SYSUI_STATE_DISABLE_GESTURE_SPLIT_INVOCATION,
SYSUI_STATE_ASSIST_GESTURE_CONSTRAINED,
SYSUI_STATE_BUBBLES_EXPANDED,
SYSUI_STATE_DIALOG_SHOWING,
@@ -211,8 +211,8 @@
if ((flags & SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE) != 0) {
str.add("a11y_long_click");
}
- if ((flags & SYSUI_STATE_TRACING_ENABLED) != 0) {
- str.add("tracing");
+ if ((flags & SYSUI_STATE_DISABLE_GESTURE_SPLIT_INVOCATION) != 0) {
+ str.add("disable_gesture_split_invocation");
}
if ((flags & SYSUI_STATE_ASSIST_GESTURE_CONSTRAINED) != 0) {
str.add("asst_gesture_constrain");
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
index c613afb..473719fa 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
@@ -141,6 +141,7 @@
private static final int ON_TASK_DESCRIPTION_CHANGED = 21;
private static final int ON_ACTIVITY_ROTATION = 22;
private static final int ON_LOCK_TASK_MODE_CHANGED = 23;
+ private static final int ON_TASK_SNAPSHOT_INVALIDATED = 24;
/**
* List of {@link TaskStackChangeListener} registered from {@link #addListener}.
@@ -272,6 +273,12 @@
}
@Override
+ public void onTaskSnapshotInvalidated(int taskId) {
+ mHandler.obtainMessage(ON_TASK_SNAPSHOT_INVALIDATED, taskId, 0 /* unused */)
+ .sendToTarget();
+ }
+
+ @Override
public void onTaskCreated(int taskId, ComponentName componentName) {
mHandler.obtainMessage(ON_TASK_CREATED, taskId, 0, componentName).sendToTarget();
}
@@ -496,6 +503,15 @@
}
break;
}
+ case ON_TASK_SNAPSHOT_INVALIDATED: {
+ Trace.beginSection("onTaskSnapshotInvalidated");
+ final ThumbnailData thumbnail = new ThumbnailData();
+ for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
+ mTaskStackListeners.get(i).onTaskSnapshotChanged(msg.arg1, thumbnail);
+ }
+ Trace.endSection();
+ break;
+ }
}
}
if (msg.obj instanceof SomeArgs) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
index 91fb688..905a98c 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -35,6 +35,7 @@
import android.app.ActivityManager;
import android.app.admin.DevicePolicyManager;
+import android.app.admin.flags.Flags;
import android.content.Intent;
import android.content.res.ColorStateList;
import android.content.res.Configuration;
@@ -134,6 +135,7 @@
private final BouncerMessageInteractor mBouncerMessageInteractor;
private int mTranslationY;
private final KeyguardTransitionInteractor mKeyguardTransitionInteractor;
+ private final DevicePolicyManager mDevicePolicyManager;
// Whether the volume keys should be handled by keyguard. If true, then
// they will be handled here for specific media types such as music, otherwise
// the audio service will bring up the volume dialog.
@@ -460,6 +462,7 @@
SelectedUserInteractor selectedUserInteractor,
DeviceProvisionedController deviceProvisionedController,
FaceAuthAccessibilityDelegate faceAuthAccessibilityDelegate,
+ DevicePolicyManager devicePolicyManager,
KeyguardTransitionInteractor keyguardTransitionInteractor,
Lazy<PrimaryBouncerInteractor> primaryBouncerInteractor,
Provider<DeviceEntryInteractor> deviceEntryInteractor
@@ -495,6 +498,7 @@
mKeyguardTransitionInteractor = keyguardTransitionInteractor;
mDeviceProvisionedController = deviceProvisionedController;
mPrimaryBouncerInteractor = primaryBouncerInteractor;
+ mDevicePolicyManager = devicePolicyManager;
}
@Override
@@ -1105,35 +1109,23 @@
if (DEBUG) Log.d(TAG, "reportFailedPatternAttempt: #" + failedAttempts);
- final DevicePolicyManager dpm = mLockPatternUtils.getDevicePolicyManager();
final int failedAttemptsBeforeWipe =
- dpm.getMaximumFailedPasswordsForWipe(null, userId);
+ mDevicePolicyManager.getMaximumFailedPasswordsForWipe(null, userId);
final int remainingBeforeWipe = failedAttemptsBeforeWipe > 0
? (failedAttemptsBeforeWipe - failedAttempts)
: Integer.MAX_VALUE; // because DPM returns 0 if no restriction
if (remainingBeforeWipe < LockPatternUtils.FAILED_ATTEMPTS_BEFORE_WIPE_GRACE) {
- // The user has installed a DevicePolicyManager that requests a user/profile to be wiped
- // N attempts. Once we get below the grace period, we post this dialog every time as a
- // clear warning until the deletion fires.
- // Check which profile has the strictest policy for failed password attempts
- final int expiringUser = dpm.getProfileWithMinimumFailedPasswordsForWipe(userId);
- int userType = USER_TYPE_PRIMARY;
- if (expiringUser == userId) {
- // TODO: http://b/23522538
- if (expiringUser != UserHandle.USER_SYSTEM) {
- userType = USER_TYPE_SECONDARY_USER;
- }
- } else if (expiringUser != UserHandle.USER_NULL) {
- userType = USER_TYPE_WORK_PROFILE;
- } // If USER_NULL, which shouldn't happen, leave it as USER_TYPE_PRIMARY
- if (remainingBeforeWipe > 0) {
- mView.showAlmostAtWipeDialog(failedAttempts, remainingBeforeWipe, userType);
- } else {
- // Too many attempts. The device will be wiped shortly.
- Slog.i(TAG, "Too many unlock attempts; user " + expiringUser + " will be wiped!");
- mView.showWipeDialog(failedAttempts, userType);
- }
+ // The user has installed a DevicePolicyManager that requests a
+ // user/profile to be wiped N attempts. Once we get below the grace period,
+ // we post this dialog every time as a clear warning until the deletion
+ // fires. Check which profile has the strictest policy for failed password
+ // attempts.
+ final int expiringUser =
+ mDevicePolicyManager.getProfileWithMinimumFailedPasswordsForWipe(userId);
+ Integer mainUser = mSelectedUserInteractor.getMainUserId();
+ showMessageForFailedUnlockAttempt(
+ userId, expiringUser, mainUser, remainingBeforeWipe, failedAttempts);
}
mLockPatternUtils.reportFailedPasswordAttempt(userId);
if (timeoutMs > 0) {
@@ -1145,6 +1137,35 @@
}
}
+ @VisibleForTesting
+ void showMessageForFailedUnlockAttempt(int userId, int expiringUserId, Integer mainUserId,
+ int remainingBeforeWipe, int failedAttempts) {
+ int userType = USER_TYPE_PRIMARY;
+ if (expiringUserId == userId) {
+ int primaryUser = UserHandle.USER_SYSTEM;
+ if (Flags.headlessSingleUserFixes()) {
+ if (mainUserId != null) {
+ primaryUser = mainUserId;
+ }
+ }
+ // TODO: http://b/23522538
+ if (expiringUserId != primaryUser) {
+ userType = USER_TYPE_SECONDARY_USER;
+ }
+ } else if (expiringUserId != UserHandle.USER_NULL) {
+ userType = USER_TYPE_WORK_PROFILE;
+ } // If USER_NULL, which shouldn't happen, leave it as USER_TYPE_PRIMARY
+ if (remainingBeforeWipe > 0) {
+ mView.showAlmostAtWipeDialog(failedAttempts, remainingBeforeWipe,
+ userType);
+ } else {
+ // Too many attempts. The device will be wiped shortly.
+ Slog.i(TAG, "Too many unlock attempts; user " + expiringUserId
+ + " will be wiped!");
+ mView.showWipeDialog(failedAttempts, userType);
+ }
+ }
+
private void getCurrentSecurityController(
KeyguardSecurityViewFlipperController.OnViewInflatedCallback onViewInflatedCallback) {
mSecurityViewFlipperController
diff --git a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
index 57c1fd0..42896a4 100644
--- a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
@@ -569,6 +569,11 @@
return true;
}
+ /** Finish the current expand motion without accounting for velocity. */
+ public void finishExpanding() {
+ finishExpanding(false, 0);
+ }
+
/**
* Finish the current expand motion
* @param forceAbort whether the expansion should be forcefully aborted and returned to the old
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/AccessibilityModule.kt b/packages/SystemUI/src/com/android/systemui/accessibility/AccessibilityModule.kt
index 35f9344..004d5db 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/AccessibilityModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/AccessibilityModule.kt
@@ -22,6 +22,8 @@
import com.android.systemui.accessibility.data.repository.ColorCorrectionRepositoryImpl
import com.android.systemui.accessibility.data.repository.ColorInversionRepository
import com.android.systemui.accessibility.data.repository.ColorInversionRepositoryImpl
+import com.android.systemui.accessibility.data.repository.OneHandedModeRepository
+import com.android.systemui.accessibility.data.repository.OneHandedModeRepositoryImpl
import com.android.systemui.accessibility.qs.QSAccessibilityModule
import dagger.Binds
import dagger.Module
@@ -34,6 +36,8 @@
@Binds
fun colorInversionRepository(impl: ColorInversionRepositoryImpl): ColorInversionRepository
+ @Binds fun oneHandedModeRepository(impl: OneHandedModeRepositoryImpl): OneHandedModeRepository
+
@Binds
fun accessibilityQsShortcutsRepository(
impl: AccessibilityQsShortcutsRepositoryImpl
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/data/repository/OneHandedModeRepository.kt b/packages/SystemUI/src/com/android/systemui/accessibility/data/repository/OneHandedModeRepository.kt
new file mode 100644
index 0000000..d921025
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/data/repository/OneHandedModeRepository.kt
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.accessibility.data.repository
+
+import android.os.UserHandle
+import android.provider.Settings
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.util.settings.SecureSettings
+import com.android.systemui.util.settings.SettingsProxyExt.observerFlow
+import javax.inject.Inject
+import kotlin.coroutines.CoroutineContext
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flowOn
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.onStart
+import kotlinx.coroutines.flow.stateIn
+import kotlinx.coroutines.withContext
+
+/** Provides data related to one handed mode. */
+interface OneHandedModeRepository {
+ /** Observable for whether one handed mode is enabled */
+ fun isEnabled(userHandle: UserHandle): Flow<Boolean>
+
+ /** Sets one handed mode enabled state. */
+ suspend fun setIsEnabled(isEnabled: Boolean, userHandle: UserHandle): Boolean
+}
+
+@SysUISingleton
+class OneHandedModeRepositoryImpl
+@Inject
+constructor(
+ @Background private val bgCoroutineContext: CoroutineContext,
+ @Application private val scope: CoroutineScope,
+ private val secureSettings: SecureSettings,
+) : OneHandedModeRepository {
+
+ private val userMap = mutableMapOf<Int, Flow<Boolean>>()
+
+ override fun isEnabled(userHandle: UserHandle): Flow<Boolean> =
+ userMap.getOrPut(userHandle.identifier) {
+ secureSettings
+ .observerFlow(userHandle.identifier, SETTING_NAME)
+ .onStart { emit(Unit) }
+ .map {
+ secureSettings.getIntForUser(SETTING_NAME, DISABLED, userHandle.identifier) ==
+ ENABLED
+ }
+ .distinctUntilChanged()
+ .flowOn(bgCoroutineContext)
+ .stateIn(scope, SharingStarted.WhileSubscribed(), DEFAULT_VALUE)
+ }
+
+ override suspend fun setIsEnabled(isEnabled: Boolean, userHandle: UserHandle): Boolean =
+ withContext(bgCoroutineContext) {
+ secureSettings.putIntForUser(
+ SETTING_NAME,
+ if (isEnabled) ENABLED else DISABLED,
+ userHandle.identifier
+ )
+ }
+
+ companion object {
+ private const val SETTING_NAME = Settings.Secure.ONE_HANDED_MODE_ENABLED
+ private const val DISABLED = 0
+ private const val ENABLED = 1
+ private const val DEFAULT_VALUE = false
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogManager.java b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogManager.java
index 623b40f..14e5f34 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogManager.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogManager.java
@@ -18,7 +18,6 @@
import android.bluetooth.BluetoothDevice;
import android.util.Log;
-import android.view.View;
import androidx.annotation.Nullable;
@@ -26,6 +25,7 @@
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.systemui.animation.DialogCuj;
import com.android.systemui.animation.DialogTransitionAnimator;
+import com.android.systemui.animation.Expandable;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.statusbar.phone.SystemUIDialog;
@@ -58,9 +58,9 @@
/**
* Shows the dialog.
*
- * @param view The view from which the dialog is shown.
+ * @param expandable {@link Expandable} from which the dialog is shown.
*/
- public void showDialog(View view) {
+ public void showDialog(Expandable expandable) {
if (mDialog != null) {
if (DEBUG) {
Log.d(TAG, "HearingDevicesDialog already showing. Destroy it first.");
@@ -70,13 +70,17 @@
mDialog = mDialogFactory.create(!isAnyBondedHearingDevice()).createDialog();
- if (view != null) {
- mDialogTransitionAnimator.showFromView(mDialog, view,
+ if (expandable != null) {
+ DialogTransitionAnimator.Controller controller = expandable.dialogTransitionController(
new DialogCuj(InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN,
- INTERACTION_JANK_TAG), /* animateBackgroundBoundsChange= */ true);
- } else {
- mDialog.show();
+ INTERACTION_JANK_TAG));
+ if (controller != null) {
+ mDialogTransitionAnimator.show(mDialog,
+ controller, /* animateBackgroundBoundsChange= */ true);
+ return;
+ }
}
+ mDialog.show();
}
private void destroyDialog() {
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/qs/QSAccessibilityModule.kt b/packages/SystemUI/src/com/android/systemui/accessibility/qs/QSAccessibilityModule.kt
index 99be762..54dd6d0 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/qs/QSAccessibilityModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/qs/QSAccessibilityModule.kt
@@ -41,6 +41,10 @@
import com.android.systemui.qs.tiles.impl.inversion.domain.interactor.ColorInversionTileDataInteractor
import com.android.systemui.qs.tiles.impl.inversion.domain.interactor.ColorInversionUserActionInteractor
import com.android.systemui.qs.tiles.impl.inversion.domain.model.ColorInversionTileModel
+import com.android.systemui.qs.tiles.impl.onehanded.domain.OneHandedModeTileDataInteractor
+import com.android.systemui.qs.tiles.impl.onehanded.domain.OneHandedModeTileUserActionInteractor
+import com.android.systemui.qs.tiles.impl.onehanded.domain.model.OneHandedModeTileModel
+import com.android.systemui.qs.tiles.impl.onehanded.ui.OneHandedModeTileMapper
import com.android.systemui.qs.tiles.impl.reducebrightness.domain.interactor.ReduceBrightColorsTileDataInteractor
import com.android.systemui.qs.tiles.impl.reducebrightness.domain.interactor.ReduceBrightColorsTileUserActionInteractor
import com.android.systemui.qs.tiles.impl.reducebrightness.domain.model.ReduceBrightColorsTileModel
@@ -256,5 +260,24 @@
),
instanceId = uiEventLogger.getNewInstanceId(),
)
+
+ /** Inject One Handed Mode Tile into tileViewModelMap in QSModule. */
+ @Provides
+ @IntoMap
+ @StringKey(ONE_HANDED_TILE_SPEC)
+ fun provideOneHandedModeTileViewModel(
+ factory: QSTileViewModelFactory.Static<OneHandedModeTileModel>,
+ mapper: OneHandedModeTileMapper,
+ stateInteractor: OneHandedModeTileDataInteractor,
+ userActionInteractor: OneHandedModeTileUserActionInteractor
+ ): QSTileViewModel =
+ if (Flags.qsNewTilesFuture())
+ factory.create(
+ TileSpec.create(ONE_HANDED_TILE_SPEC),
+ userActionInteractor,
+ stateInteractor,
+ mapper,
+ )
+ else StubQSTileViewModel
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/ambient/touch/BouncerSwipeTouchHandler.java b/packages/SystemUI/src/com/android/systemui/ambient/touch/BouncerSwipeTouchHandler.java
index 85aeb27..019f498 100644
--- a/packages/SystemUI/src/com/android/systemui/ambient/touch/BouncerSwipeTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/ambient/touch/BouncerSwipeTouchHandler.java
@@ -254,7 +254,11 @@
mVelocityTracker = mVelocityTrackerFactory.obtain();
mTouchSession = session;
mVelocityTracker.clear();
- mNotificationShadeWindowController.setForcePluginOpen(true, this);
+
+ if (!Flags.communalBouncerDoNotModifyPluginOpen()) {
+ mNotificationShadeWindowController.setForcePluginOpen(true, this);
+ }
+
mScrimManager.addCallback(mScrimManagerCallback);
mCurrentScrimController = mScrimManager.getCurrentController();
@@ -265,7 +269,10 @@
}
mScrimManager.removeCallback(mScrimManagerCallback);
mCapture = null;
- mNotificationShadeWindowController.setForcePluginOpen(false, this);
+
+ if (!Flags.communalBouncerDoNotModifyPluginOpen()) {
+ mNotificationShadeWindowController.setForcePluginOpen(false, this);
+ }
});
session.registerGestureListener(mOnGestureListener);
diff --git a/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt b/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt
index 5df7fc9..fcba425 100644
--- a/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt
@@ -16,6 +16,7 @@
package com.android.systemui.authentication.domain.interactor
+import android.app.admin.flags.Flags
import android.os.UserHandle
import com.android.internal.widget.LockPatternUtils
import com.android.internal.widget.LockPatternView
@@ -288,9 +289,15 @@
private suspend fun getWipeTarget(): WipeTarget {
// Check which profile has the strictest policy for failed authentication attempts.
val userToBeWiped = repository.getProfileWithMinFailedUnlockAttemptsForWipe()
+ val primaryUser =
+ if (Flags.headlessSingleUserFixes()) {
+ selectedUserInteractor.getMainUserId() ?: UserHandle.USER_SYSTEM
+ } else {
+ UserHandle.USER_SYSTEM
+ }
return when (userToBeWiped) {
selectedUserInteractor.getSelectedUserId() ->
- if (userToBeWiped == UserHandle.USER_SYSTEM) {
+ if (userToBeWiped == primaryUser) {
WipeTarget.WholeDevice
} else {
WipeTarget.User
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/shared/model/GridLayoutTypeKey.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogModule.kt
similarity index 63%
copy from packages/SystemUI/src/com/android/systemui/qs/panels/shared/model/GridLayoutTypeKey.kt
copy to packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogModule.kt
index 0dbaaba..2e9169e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/shared/model/GridLayoutTypeKey.kt
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogModule.kt
@@ -13,16 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package com.android.systemui.bluetooth.qsdialog
-package com.android.systemui.qs.panels.shared.model
+import com.android.systemui.dagger.SysUISingleton
+import dagger.Binds
+import dagger.Module
-import dagger.MapKey
-import kotlin.reflect.KClass
-
-/**
- * Dagger map key to associate a [GridLayoutType] with its
- * [com.android.systemui.qs.panels.ui.compose.GridLayout].
- */
-@Retention(AnnotationRetention.RUNTIME)
-@MapKey
-annotation class GridLayoutTypeKey(val value: KClass<out GridLayoutType>)
+@Module
+interface BluetoothTileDialogModule {
+ @Binds
+ @SysUISingleton
+ fun bindDeviceItemActionInteractor(
+ impl: DeviceItemActionInteractorImpl
+ ): DeviceItemActionInteractor
+}
diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModel.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModel.kt
index eb919e3..94f465d 100644
--- a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModel.kt
@@ -32,6 +32,7 @@
import com.android.systemui.Prefs
import com.android.systemui.animation.DialogCuj
import com.android.systemui.animation.DialogTransitionAnimator
+import com.android.systemui.animation.Expandable
import com.android.systemui.bluetooth.qsdialog.BluetoothTileDialogDelegate.Companion.ACTION_AUDIO_SHARING
import com.android.systemui.bluetooth.qsdialog.BluetoothTileDialogDelegate.Companion.ACTION_BLUETOOTH_DEVICE_DETAILS
import com.android.systemui.bluetooth.qsdialog.BluetoothTileDialogDelegate.Companion.ACTION_PAIR_NEW_DEVICE
@@ -61,6 +62,7 @@
@Inject
constructor(
private val deviceItemInteractor: DeviceItemInteractor,
+ private val deviceItemActionInteractor: DeviceItemActionInteractor,
private val bluetoothStateInteractor: BluetoothStateInteractor,
private val bluetoothAutoOnInteractor: BluetoothAutoOnInteractor,
private val audioSharingInteractor: AudioSharingInteractor,
@@ -82,7 +84,7 @@
* @param view The view from which the dialog is shown.
*/
@kotlinx.coroutines.ExperimentalCoroutinesApi
- fun showDialog(view: View?) {
+ fun showDialog(expandable: Expandable?) {
cancelJob()
job =
@@ -93,17 +95,15 @@
val dialog = dialogDelegate.createDialog()
val context = dialog.context
- view?.let {
- dialogTransitionAnimator.showFromView(
- dialog,
- it,
- animateBackgroundBoundsChange = true,
- cuj =
- DialogCuj(
- InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN,
- INTERACTION_JANK_TAG
- )
+ val controller =
+ expandable?.dialogTransitionController(
+ DialogCuj(
+ InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN,
+ INTERACTION_JANK_TAG
+ )
)
+ controller?.let {
+ dialogTransitionAnimator.show(dialog, it, animateBackgroundBoundsChange = true)
}
?: dialog.show()
@@ -193,7 +193,7 @@
// deviceItemClick is emitted when user clicked on a device item.
dialogDelegate.deviceItemClick
- .onEach { deviceItemInteractor.updateDeviceItemOnClick(it) }
+ .onEach { deviceItemActionInteractor.onClick(it, dialog) }
.launchIn(this)
// contentHeight is emitted when the dialog is dismissed.
diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemActionInteractor.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemActionInteractor.kt
new file mode 100644
index 0000000..9311760
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemActionInteractor.kt
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.bluetooth.qsdialog
+
+import com.android.internal.logging.UiEventLogger
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.statusbar.phone.SystemUIDialog
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.withContext
+
+/** Defines interface for click handling of a DeviceItem. */
+interface DeviceItemActionInteractor {
+ suspend fun onClick(deviceItem: DeviceItem, dialog: SystemUIDialog)
+}
+
+@SysUISingleton
+open class DeviceItemActionInteractorImpl
+@Inject
+constructor(
+ @Background private val backgroundDispatcher: CoroutineDispatcher,
+ private val logger: BluetoothTileDialogLogger,
+ private val uiEventLogger: UiEventLogger,
+) : DeviceItemActionInteractor {
+
+ override suspend fun onClick(deviceItem: DeviceItem, dialog: SystemUIDialog) {
+ withContext(backgroundDispatcher) {
+ logger.logDeviceClick(deviceItem.cachedBluetoothDevice.address, deviceItem.type)
+
+ deviceItem.cachedBluetoothDevice.apply {
+ when (deviceItem.type) {
+ DeviceItemType.ACTIVE_MEDIA_BLUETOOTH_DEVICE -> {
+ disconnect()
+ uiEventLogger.log(BluetoothTileDialogUiEvent.ACTIVE_DEVICE_DISCONNECT)
+ }
+ DeviceItemType.AUDIO_SHARING_MEDIA_BLUETOOTH_DEVICE -> {
+ uiEventLogger.log(BluetoothTileDialogUiEvent.AUDIO_SHARING_DEVICE_CLICKED)
+ }
+ DeviceItemType.AVAILABLE_MEDIA_BLUETOOTH_DEVICE -> {
+ setActive()
+ uiEventLogger.log(BluetoothTileDialogUiEvent.CONNECTED_DEVICE_SET_ACTIVE)
+ }
+ DeviceItemType.CONNECTED_BLUETOOTH_DEVICE -> {
+ disconnect()
+ uiEventLogger.log(
+ BluetoothTileDialogUiEvent.CONNECTED_OTHER_DEVICE_DISCONNECT
+ )
+ }
+ DeviceItemType.SAVED_BLUETOOTH_DEVICE -> {
+ connect()
+ uiEventLogger.log(BluetoothTileDialogUiEvent.SAVED_DEVICE_CONNECT)
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractor.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractor.kt
index 66e593b..1526cd9 100644
--- a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractor.kt
@@ -20,7 +20,6 @@
import android.bluetooth.BluetoothDevice
import android.content.Context
import android.media.AudioManager
-import com.android.internal.logging.UiEventLogger
import com.android.settingslib.bluetooth.BluetoothCallback
import com.android.settingslib.bluetooth.CachedBluetoothDevice
import com.android.settingslib.bluetooth.LocalBluetoothManager
@@ -52,7 +51,6 @@
private val bluetoothAdapter: BluetoothAdapter? = BluetoothAdapter.getDefaultAdapter(),
private val localBluetoothManager: LocalBluetoothManager?,
private val systemClock: SystemClock,
- private val uiEventLogger: UiEventLogger,
private val logger: BluetoothTileDialogLogger,
@Application private val coroutineScope: CoroutineScope,
@Background private val backgroundDispatcher: CoroutineDispatcher,
@@ -169,38 +167,6 @@
)
}
- internal suspend fun updateDeviceItemOnClick(deviceItem: DeviceItem) {
- withContext(backgroundDispatcher) {
- logger.logDeviceClick(deviceItem.cachedBluetoothDevice.address, deviceItem.type)
-
- deviceItem.cachedBluetoothDevice.apply {
- when (deviceItem.type) {
- DeviceItemType.ACTIVE_MEDIA_BLUETOOTH_DEVICE -> {
- disconnect()
- uiEventLogger.log(BluetoothTileDialogUiEvent.ACTIVE_DEVICE_DISCONNECT)
- }
- DeviceItemType.AUDIO_SHARING_MEDIA_BLUETOOTH_DEVICE -> {
- uiEventLogger.log(BluetoothTileDialogUiEvent.AUDIO_SHARING_DEVICE_CLICKED)
- }
- DeviceItemType.AVAILABLE_MEDIA_BLUETOOTH_DEVICE -> {
- setActive()
- uiEventLogger.log(BluetoothTileDialogUiEvent.CONNECTED_DEVICE_SET_ACTIVE)
- }
- DeviceItemType.CONNECTED_BLUETOOTH_DEVICE -> {
- disconnect()
- uiEventLogger.log(
- BluetoothTileDialogUiEvent.CONNECTED_OTHER_DEVICE_DISCONNECT
- )
- }
- DeviceItemType.SAVED_BLUETOOTH_DEVICE -> {
- connect()
- uiEventLogger.log(BluetoothTileDialogUiEvent.SAVED_DEVICE_CONNECT)
- }
- }
- }
- }
- }
-
internal fun setDeviceItemFactoryListForTesting(list: List<DeviceItemFactory>) {
deviceItemFactoryList = list
}
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/data/repository/KeyguardBouncerRepository.kt b/packages/SystemUI/src/com/android/systemui/bouncer/data/repository/KeyguardBouncerRepository.kt
index 0534824..f1c3f94 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/data/repository/KeyguardBouncerRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/data/repository/KeyguardBouncerRepository.kt
@@ -323,6 +323,9 @@
alternateBouncerUIAvailable
.logDiffsForTable(buffer, "", "IsAlternateBouncerUIAvailable", false)
.launchIn(applicationScope)
+ alternateBouncerVisible
+ .logDiffsForTable(buffer, "", "AlternateBouncerVisible", false)
+ .launchIn(applicationScope)
lastShownSecurityMode
.map { it.name }
.logDiffsForTable(buffer, "", "lastShownSecurityMode", null)
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractor.kt
index fa19bf4..e0334a0 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractor.kt
@@ -29,7 +29,7 @@
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.policy.KeyguardStateController
-import com.android.systemui.util.kotlin.BooleanFlowOperators.or
+import com.android.systemui.util.kotlin.BooleanFlowOperators.anyOf
import com.android.systemui.util.time.SystemClock
import dagger.Lazy
import javax.inject.Inject
@@ -78,7 +78,7 @@
bouncerRepository.alternateBouncerUIAvailable
}
private val isDozingOrAod: Flow<Boolean> =
- or(
+ anyOf(
keyguardTransitionInteractor.get().transitionValue(KeyguardState.DOZING).map {
it > 0f
},
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java
index beaa170..b42a903 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java
@@ -206,7 +206,7 @@
);
final CommunalInteractor communalInteractor = mCommunalInteractorLazy.get();
mJavaAdapter.alwaysCollectFlow(
- BooleanFlowOperators.INSTANCE.and(
+ BooleanFlowOperators.INSTANCE.allOf(
communalInteractor.isCommunalEnabled(),
communalInteractor.isCommunalShowing()),
this::onShowingCommunalHubChanged
@@ -292,6 +292,7 @@
@Override
public void onKeyEvent(KeyEvent ev) {
+ logDebug("REAL: onKeyEvent(" + KeyEvent.actionToString(ev.getAction()) + ")");
// Only collect if it is an ACTION_UP action and is allow-listed
if (ev.getAction() == KeyEvent.ACTION_UP && mAcceptedKeycodes.contains(ev.getKeyCode())) {
mFalsingDataProvider.onKeyEvent(ev);
@@ -300,7 +301,7 @@
@Override
public void onTouchEvent(MotionEvent ev) {
- logDebug("REAL: onTouchEvent(" + ev.getActionMasked() + ")");
+ logDebug("REAL: onTouchEvent(" + MotionEvent.actionToString(ev.getActionMasked()) + ")");
if (!mKeyguardStateController.isShowing()) {
avoidGesture();
return;
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorNoOp.kt b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorNoOp.kt
index b289fa4..6b22137 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorNoOp.kt
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorNoOp.kt
@@ -61,11 +61,11 @@
}
override fun onKeyEvent(ev: KeyEvent) {
- logDebug("NOOP: onKeyEvent(${ev.action}")
+ logDebug("NOOP: onKeyEvent(${KeyEvent.actionToString(ev.action)}")
}
override fun onTouchEvent(ev: MotionEvent) {
- logDebug("NOOP: onTouchEvent(${ev.actionMasked})")
+ logDebug("NOOP: onTouchEvent(${MotionEvent.actionToString(ev.actionMasked)})")
}
override fun onMotionEventComplete() {
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayView.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayView.java
index b269967..8efc66d 100644
--- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayView.java
+++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayView.java
@@ -18,6 +18,8 @@
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
+import static com.android.systemui.Flags.screenshotShelfUi2;
+
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
@@ -25,6 +27,7 @@
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.annotation.Nullable;
+import android.app.PendingIntent;
import android.app.RemoteAction;
import android.content.Context;
import android.content.res.Resources;
@@ -36,6 +39,7 @@
import android.graphics.drawable.Icon;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
+import android.util.Log;
import android.util.MathUtils;
import android.util.TypedValue;
import android.view.DisplayCutout;
@@ -58,9 +62,15 @@
import com.android.systemui.screenshot.DraggableConstraintLayout;
import com.android.systemui.screenshot.FloatingWindowUtil;
import com.android.systemui.screenshot.OverlayActionChip;
+import com.android.systemui.screenshot.ui.binder.ActionButtonViewBinder;
+import com.android.systemui.screenshot.ui.viewmodel.ActionButtonAppearance;
+import com.android.systemui.screenshot.ui.viewmodel.ActionButtonViewModel;
import java.util.ArrayList;
+import kotlin.Unit;
+import kotlin.jvm.functions.Function0;
+
/**
* Handles the visual elements and animations for the clipboard overlay.
*/
@@ -85,7 +95,7 @@
private final DisplayMetrics mDisplayMetrics;
private final AccessibilityManager mAccessibilityManager;
- private final ArrayList<OverlayActionChip> mActionChips = new ArrayList<>();
+ private final ArrayList<View> mActionChips = new ArrayList<>();
private View mClipboardPreview;
private ImageView mImagePreview;
@@ -93,11 +103,12 @@
private TextView mHiddenPreview;
private LinearLayout mMinimizedPreview;
private View mPreviewBorder;
- private OverlayActionChip mShareChip;
- private OverlayActionChip mRemoteCopyChip;
+ private View mShareChip;
+ private View mRemoteCopyChip;
private View mActionContainerBackground;
private View mDismissButton;
private LinearLayout mActionContainer;
+ private ClipboardOverlayCallbacks mClipboardCallbacks;
public ClipboardOverlayView(Context context) {
this(context, null);
@@ -128,17 +139,7 @@
mRemoteCopyChip = requireViewById(R.id.remote_copy_chip);
mDismissButton = requireViewById(R.id.dismiss_button);
- mShareChip.setAlpha(1);
- mRemoteCopyChip.setAlpha(1);
- mShareChip.setContentDescription(mContext.getString(com.android.internal.R.string.share));
-
- mRemoteCopyChip.setIcon(
- Icon.createWithResource(mContext, R.drawable.ic_baseline_devices_24), true);
- mShareChip.setIcon(
- Icon.createWithResource(mContext, R.drawable.ic_screenshot_share), true);
-
- mRemoteCopyChip.setContentDescription(
- mContext.getString(R.string.clipboard_send_nearby_description));
+ bindDefaultActionChips();
mTextPreview.getViewTreeObserver().addOnPreDrawListener(() -> {
int availableHeight = mTextPreview.getHeight()
@@ -149,15 +150,68 @@
super.onFinishInflate();
}
+ private void bindDefaultActionChips() {
+ if (screenshotShelfUi2()) {
+ ActionButtonViewBinder.INSTANCE.bind(mRemoteCopyChip,
+ ActionButtonViewModel.Companion.withNextId(
+ new ActionButtonAppearance(
+ Icon.createWithResource(mContext,
+ R.drawable.ic_baseline_devices_24).loadDrawable(
+ mContext),
+ null,
+ mContext.getString(R.string.clipboard_send_nearby_description)),
+ new Function0<>() {
+ @Override
+ public Unit invoke() {
+ if (mClipboardCallbacks != null) {
+ mClipboardCallbacks.onRemoteCopyButtonTapped();
+ }
+ return null;
+ }
+ }));
+ ActionButtonViewBinder.INSTANCE.bind(mShareChip,
+ ActionButtonViewModel.Companion.withNextId(
+ new ActionButtonAppearance(
+ Icon.createWithResource(mContext,
+ R.drawable.ic_screenshot_share).loadDrawable(mContext),
+ null, mContext.getString(com.android.internal.R.string.share)),
+ new Function0<>() {
+ @Override
+ public Unit invoke() {
+ if (mClipboardCallbacks != null) {
+ mClipboardCallbacks.onShareButtonTapped();
+ }
+ return null;
+ }
+ }));
+ } else {
+ mShareChip.setAlpha(1);
+ mRemoteCopyChip.setAlpha(1);
+
+ ((ImageView) mRemoteCopyChip.findViewById(R.id.overlay_action_chip_icon)).setImageIcon(
+ Icon.createWithResource(mContext, R.drawable.ic_baseline_devices_24));
+ ((ImageView) mShareChip.findViewById(R.id.overlay_action_chip_icon)).setImageIcon(
+ Icon.createWithResource(mContext, R.drawable.ic_screenshot_share));
+
+ mShareChip.setContentDescription(
+ mContext.getString(com.android.internal.R.string.share));
+ mRemoteCopyChip.setContentDescription(
+ mContext.getString(R.string.clipboard_send_nearby_description));
+ }
+ }
+
@Override
public void setCallbacks(SwipeDismissCallbacks callbacks) {
super.setCallbacks(callbacks);
ClipboardOverlayCallbacks clipboardCallbacks = (ClipboardOverlayCallbacks) callbacks;
- mShareChip.setOnClickListener(v -> clipboardCallbacks.onShareButtonTapped());
+ if (!screenshotShelfUi2()) {
+ mShareChip.setOnClickListener(v -> clipboardCallbacks.onShareButtonTapped());
+ mRemoteCopyChip.setOnClickListener(v -> clipboardCallbacks.onRemoteCopyButtonTapped());
+ }
mDismissButton.setOnClickListener(v -> clipboardCallbacks.onDismissButtonTapped());
- mRemoteCopyChip.setOnClickListener(v -> clipboardCallbacks.onRemoteCopyButtonTapped());
mClipboardPreview.setOnClickListener(v -> clipboardCallbacks.onPreviewTapped());
mMinimizedPreview.setOnClickListener(v -> clipboardCallbacks.onMinimizedViewTapped());
+ mClipboardCallbacks = clipboardCallbacks;
}
void setEditAccessibilityAction(boolean editable) {
@@ -285,7 +339,7 @@
}
void resetActionChips() {
- for (OverlayActionChip chip : mActionChips) {
+ for (View chip : mActionChips) {
mActionContainer.removeView(chip);
}
mActionChips.clear();
@@ -437,7 +491,12 @@
void setActionChip(RemoteAction action, Runnable onFinish) {
mActionContainerBackground.setVisibility(View.VISIBLE);
- OverlayActionChip chip = constructActionChip(action, onFinish);
+ View chip;
+ if (screenshotShelfUi2()) {
+ chip = constructShelfActionChip(action, onFinish);
+ } else {
+ chip = constructActionChip(action, onFinish);
+ }
mActionContainer.addView(chip);
mActionChips.add(chip);
}
@@ -450,6 +509,27 @@
v.setVisibility(View.VISIBLE);
}
+ private View constructShelfActionChip(RemoteAction action, Runnable onFinish) {
+ View chip = LayoutInflater.from(mContext).inflate(
+ R.layout.shelf_action_chip, mActionContainer, false);
+ ActionButtonViewBinder.INSTANCE.bind(chip, ActionButtonViewModel.Companion.withNextId(
+ new ActionButtonAppearance(action.getIcon().loadDrawable(mContext),
+ action.getTitle(), action.getTitle()), new Function0<>() {
+ @Override
+ public Unit invoke() {
+ try {
+ action.getActionIntent().send();
+ onFinish.run();
+ } catch (PendingIntent.CanceledException e) {
+ Log.e(TAG, "Failed to send intent");
+ }
+ return null;
+ }
+ }));
+
+ return chip;
+ }
+
private OverlayActionChip constructActionChip(RemoteAction action, Runnable onFinish) {
OverlayActionChip chip = (OverlayActionChip) LayoutInflater.from(mContext).inflate(
R.layout.overlay_action_chip, mActionContainer, false);
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/dagger/ClipboardOverlayModule.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/dagger/ClipboardOverlayModule.java
index ff9fba4..740a93e 100644
--- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/dagger/ClipboardOverlayModule.java
+++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/dagger/ClipboardOverlayModule.java
@@ -18,6 +18,8 @@
import static android.view.WindowManager.LayoutParams.TYPE_SCREENSHOT;
+import static com.android.systemui.Flags.screenshotShelfUi2;
+
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import android.content.Context;
@@ -57,8 +59,13 @@
*/
@Provides
static ClipboardOverlayView provideClipboardOverlayView(@OverlayWindowContext Context context) {
- return (ClipboardOverlayView) LayoutInflater.from(context).inflate(
- R.layout.clipboard_overlay, null);
+ if (screenshotShelfUi2()) {
+ return (ClipboardOverlayView) LayoutInflater.from(context).inflate(
+ R.layout.clipboard_overlay2, null);
+ } else {
+ return (ClipboardOverlayView) LayoutInflater.from(context).inflate(
+ R.layout.clipboard_overlay, null);
+ }
}
@Qualifier
diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/view/LongPressHandlingView.kt b/packages/SystemUI/src/com/android/systemui/common/ui/view/LongPressHandlingView.kt
index 0781451..85e2bdb 100644
--- a/packages/SystemUI/src/com/android/systemui/common/ui/view/LongPressHandlingView.kt
+++ b/packages/SystemUI/src/com/android/systemui/common/ui/view/LongPressHandlingView.kt
@@ -37,7 +37,7 @@
class LongPressHandlingView(
context: Context,
attrs: AttributeSet?,
- private val longPressDuration: () -> Long,
+ longPressDuration: () -> Long,
) :
View(
context,
@@ -89,6 +89,12 @@
)
}
+ var longPressDuration: () -> Long
+ get() = interactionHandler.longPressDuration
+ set(longPressDuration) {
+ interactionHandler.longPressDuration = longPressDuration
+ }
+
fun setLongPressHandlingEnabled(isEnabled: Boolean) {
interactionHandler.isLongPressHandlingEnabled = isEnabled
}
diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/view/LongPressHandlingViewInteractionHandler.kt b/packages/SystemUI/src/com/android/systemui/common/ui/view/LongPressHandlingViewInteractionHandler.kt
index a742e8d..d3fc610 100644
--- a/packages/SystemUI/src/com/android/systemui/common/ui/view/LongPressHandlingViewInteractionHandler.kt
+++ b/packages/SystemUI/src/com/android/systemui/common/ui/view/LongPressHandlingViewInteractionHandler.kt
@@ -34,7 +34,7 @@
/** Callback reporting the a single tap gesture was detected at the given coordinates. */
private val onSingleTapDetected: () -> Unit,
/** Time for the touch to be considered a long-press in ms */
- private val longPressDuration: () -> Long,
+ var longPressDuration: () -> Long,
) {
sealed class MotionEventModel {
object Other : MotionEventModel()
diff --git a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt
index 7448e14..5091a99 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt
@@ -44,9 +44,10 @@
import com.android.systemui.communal.widgets.WidgetConfigurator
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.dock.DockManager
-import com.android.systemui.dock.retrieveIsDocked
+import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
+import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.core.Logger
import com.android.systemui.log.dagger.CommunalLog
@@ -59,11 +60,12 @@
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.settings.UserTracker
import com.android.systemui.smartspace.data.repository.SmartspaceRepository
-import com.android.systemui.util.kotlin.BooleanFlowOperators.and
+import com.android.systemui.util.kotlin.BooleanFlowOperators.allOf
+import com.android.systemui.util.kotlin.BooleanFlowOperators.anyOf
import com.android.systemui.util.kotlin.BooleanFlowOperators.not
-import com.android.systemui.util.kotlin.BooleanFlowOperators.or
import com.android.systemui.util.kotlin.emitOnStart
import javax.inject.Inject
+import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.BufferOverflow
@@ -77,9 +79,11 @@
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.emptyFlow
+import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.shareIn
@@ -92,6 +96,7 @@
@Inject
constructor(
@Application val applicationScope: CoroutineScope,
+ @Background val bgDispatcher: CoroutineDispatcher,
broadcastDispatcher: BroadcastDispatcher,
private val communalRepository: CommunalRepository,
private val widgetRepository: CommunalWidgetRepository,
@@ -99,13 +104,13 @@
mediaRepository: CommunalMediaRepository,
smartspaceRepository: SmartspaceRepository,
keyguardInteractor: KeyguardInteractor,
- private val communalSettingsInteractor: CommunalSettingsInteractor,
+ keyguardTransitionInteractor: KeyguardTransitionInteractor,
+ communalSettingsInteractor: CommunalSettingsInteractor,
private val appWidgetHost: CommunalAppWidgetHost,
private val editWidgetsActivityStarter: EditWidgetsActivityStarter,
private val userTracker: UserTracker,
private val activityStarter: ActivityStarter,
private val userManager: UserManager,
- private val dockManager: DockManager,
sceneInteractor: SceneInteractor,
@CommunalLog logBuffer: LogBuffer,
@CommunalTableLog tableLogBuffer: TableLogBuffer,
@@ -122,10 +127,10 @@
/** Whether communal features are enabled and available. */
val isCommunalAvailable: Flow<Boolean> =
- and(
+ allOf(
communalSettingsInteractor.isCommunalEnabled,
not(keyguardInteractor.isEncryptedOrLockdown),
- or(keyguardInteractor.isKeyguardShowing, keyguardInteractor.isDreaming)
+ anyOf(keyguardInteractor.isKeyguardShowing, keyguardInteractor.isDreaming)
)
.distinctUntilChanged()
.onEach { available ->
@@ -145,8 +150,18 @@
replay = 1,
)
- /** Whether to show communal by default */
- val showByDefault: Flow<Boolean> = and(isCommunalAvailable, dockManager.retrieveIsDocked())
+ /** Whether to show communal when exiting the occluded state. */
+ val showCommunalFromOccluded: Flow<Boolean> =
+ keyguardTransitionInteractor.startedKeyguardTransitionStep
+ .filter { step -> step.to == KeyguardState.OCCLUDED }
+ .combine(isCommunalAvailable, ::Pair)
+ .map { (step, available) -> available && step.from == KeyguardState.GLANCEABLE_HUB }
+ .flowOn(bgDispatcher)
+ .stateIn(
+ scope = applicationScope,
+ started = SharingStarted.WhileSubscribed(),
+ initialValue = false,
+ )
/**
* Target scene as requested by the underlying [SceneTransitionLayout] or through [changeScene].
@@ -201,7 +216,7 @@
.flatMapLatest { state ->
when (state) {
is ObservableTransitionState.Idle ->
- flowOf(CommunalTransitionProgress.Idle(state.scene))
+ flowOf(CommunalTransitionProgress.Idle(state.currentScene))
is ObservableTransitionState.Transition ->
if (state.toScene == targetScene) {
state.progress.map {
@@ -264,7 +279,9 @@
*/
val isIdleOnCommunal: StateFlow<Boolean> =
communalRepository.transitionState
- .map { it is ObservableTransitionState.Idle && it.scene == CommunalScenes.Communal }
+ .map {
+ it is ObservableTransitionState.Idle && it.currentScene == CommunalScenes.Communal
+ }
.stateIn(
scope = applicationScope,
started = SharingStarted.Eagerly,
@@ -278,7 +295,7 @@
*/
val isCommunalVisible: Flow<Boolean> =
communalRepository.transitionState.map {
- !(it is ObservableTransitionState.Idle && it.scene == CommunalScenes.Blank)
+ !(it is ObservableTransitionState.Idle && it.currentScene == CommunalScenes.Blank)
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/communal/log/CommunalLoggerStartable.kt b/packages/SystemUI/src/com/android/systemui/communal/log/CommunalLoggerStartable.kt
index f2b4738..81feb44 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/log/CommunalLoggerStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/log/CommunalLoggerStartable.kt
@@ -88,12 +88,12 @@
/** Whether currently in communal scene. */
private fun ObservableTransitionState.isOnCommunal(): Boolean {
- return this is ObservableTransitionState.Idle && scene == CommunalScenes.Communal
+ return this is ObservableTransitionState.Idle && currentScene == CommunalScenes.Communal
}
/** Whether currently in a scene other than communal. */
private fun ObservableTransitionState.isNotOnCommunal(): Boolean {
- return this is ObservableTransitionState.Idle && scene != CommunalScenes.Communal
+ return this is ObservableTransitionState.Idle && currentScene != CommunalScenes.Communal
}
/** Whether currently transitioning from another scene to communal. */
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalTransitionViewModel.kt
index 1bee83b..337d873 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalTransitionViewModel.kt
@@ -63,8 +63,8 @@
)
.distinctUntilChanged()
- /** Whether to show communal by default */
- val showByDefault: Flow<Boolean> = communalInteractor.showByDefault
+ /** Whether to show communal when exiting the occluded state. */
+ val showCommunalFromOccluded: Flow<Boolean> = communalInteractor.showCommunalFromOccluded
val transitionFromOccludedEnded =
keyguardTransitionInteractor.transitionStepsFromState(KeyguardState.OCCLUDED).filter { step
@@ -74,8 +74,11 @@
}
val recentsBackgroundColor: Flow<Color?> =
- combine(showByDefault, communalColors.backgroundColor) { showByDefault, backgroundColor ->
- if (showByDefault) {
+ combine(showCommunalFromOccluded, communalColors.backgroundColor) {
+ showCommunalFromOccluded,
+ backgroundColor,
+ ->
+ if (showCommunalFromOccluded) {
backgroundColor
} else {
null
diff --git a/packages/SystemUI/src/com/android/systemui/communal/widgets/CommunalAppWidgetHostStartable.kt b/packages/SystemUI/src/com/android/systemui/communal/widgets/CommunalAppWidgetHostStartable.kt
index 8390d62..2ccab07 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/widgets/CommunalAppWidgetHostStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/widgets/CommunalAppWidgetHostStartable.kt
@@ -23,7 +23,7 @@
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.settings.UserTracker
-import com.android.systemui.util.kotlin.BooleanFlowOperators.or
+import com.android.systemui.util.kotlin.BooleanFlowOperators.anyOf
import com.android.systemui.util.kotlin.pairwise
import com.android.systemui.util.kotlin.sample
import javax.inject.Inject
@@ -46,7 +46,7 @@
) : CoreStartable {
override fun start() {
- or(communalInteractor.isCommunalAvailable, communalInteractor.editModeOpen)
+ anyOf(communalInteractor.isCommunalAvailable, communalInteractor.editModeOpen)
// Only trigger updates on state changes, ignoring the initial false value.
.pairwise(false)
.filter { (previous, new) -> previous != new }
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java b/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java
index 98ca09d..ef3f10f 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java
@@ -76,6 +76,7 @@
import android.net.NetworkScoreManager;
import android.net.wifi.WifiManager;
import android.os.BatteryStats;
+import android.os.IDeviceIdleController;
import android.os.PowerExemptionManager;
import android.os.PowerManager;
import android.os.ServiceManager;
@@ -735,4 +736,11 @@
static Optional<SatelliteManager> provideSatelliteManager(Context context) {
return Optional.ofNullable(context.getSystemService(SatelliteManager.class));
}
+
+ @Provides
+ @Singleton
+ static IDeviceIdleController provideDeviceIdleController() {
+ return IDeviceIdleController.Stub.asInterface(
+ ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepository.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepository.kt
index ba45a51..30a56a2 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepository.kt
@@ -46,7 +46,6 @@
import com.android.systemui.keyguard.data.repository.FaceAuthTableLog
import com.android.systemui.keyguard.data.repository.FaceDetectTableLog
import com.android.systemui.keyguard.data.repository.KeyguardRepository
-import com.android.systemui.keyguard.data.repository.TrustRepository
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.shared.model.KeyguardState
@@ -64,6 +63,7 @@
import com.google.errorprone.annotations.CompileTimeConstant
import java.io.PrintWriter
import java.util.Arrays
+import java.util.concurrent.Executor
import java.util.stream.Collectors
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
@@ -150,12 +150,12 @@
@Application private val applicationScope: CoroutineScope,
@Main private val mainDispatcher: CoroutineDispatcher,
@Background private val backgroundDispatcher: CoroutineDispatcher,
+ @Background private val backgroundExecutor: Executor,
private val sessionTracker: SessionTracker,
private val uiEventsLogger: UiEventLogger,
private val faceAuthLogger: FaceAuthenticationLogger,
private val biometricSettingsRepository: BiometricSettingsRepository,
private val deviceEntryFingerprintAuthRepository: DeviceEntryFingerprintAuthRepository,
- trustRepository: TrustRepository,
private val keyguardRepository: KeyguardRepository,
private val powerInteractor: PowerInteractor,
private val keyguardInteractor: KeyguardInteractor,
@@ -235,7 +235,10 @@
}
init {
- faceManager?.addLockoutResetCallback(faceLockoutResetCallback)
+ backgroundExecutor.execute {
+ faceManager?.addLockoutResetCallback(faceLockoutResetCallback)
+ faceAuthLogger.addLockoutResetCallbackDone()
+ }
faceAcquiredInfoIgnoreList =
Arrays.stream(
context.resources.getIntArray(
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt
index 662974d..d079a95 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt
@@ -240,6 +240,15 @@
}
/**
+ * Whether the lockscreen is enabled for the current user. This is `true` whenever the user has
+ * chosen any secure authentication method and even if they set the lockscreen to be dismissed
+ * when the user swipes on it.
+ */
+ suspend fun isLockscreenEnabled(): Boolean {
+ return repository.isLockscreenEnabled()
+ }
+
+ /**
* Whether lockscreen bypass is enabled. When enabled, the lockscreen will be automatically
* dismissed once the authentication challenge is completed. For example, completing a biometric
* authentication challenge via face unlock or fingerprint sensor can automatically bypass the
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntrySourceInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntrySourceInteractor.kt
index d4f76a8..0b9336f 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntrySourceInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntrySourceInteractor.kt
@@ -18,7 +18,7 @@
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
-import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
+import com.android.systemui.keyguard.shared.model.BiometricUnlockMode
import com.android.systemui.keyguard.shared.model.BiometricUnlockSource
import com.android.systemui.util.kotlin.sample
import javax.inject.Inject
@@ -46,10 +46,9 @@
) {
val deviceEntryFromBiometricSource: Flow<BiometricUnlockSource> =
keyguardInteractor.biometricUnlockState
- .filter { BiometricUnlockModel.dismissesKeyguard(it) }
- .sample(
- keyguardInteractor.biometricUnlockSource.filterNotNull(),
- )
+ .filter { BiometricUnlockMode.dismissesKeyguard(it.mode) }
+ .map { it.source }
+ .filterNotNull()
private val attemptEnterDeviceFromDeviceEntryIcon: MutableSharedFlow<Unit> = MutableSharedFlow()
val deviceEntryFromDeviceEntryIcon: Flow<Unit> =
diff --git a/packages/SystemUI/src/com/android/systemui/haptics/qs/QSLongPressEffect.kt b/packages/SystemUI/src/com/android/systemui/haptics/qs/QSLongPressEffect.kt
index db2ec8f..ea8d7d7 100644
--- a/packages/SystemUI/src/com/android/systemui/haptics/qs/QSLongPressEffect.kt
+++ b/packages/SystemUI/src/com/android/systemui/haptics/qs/QSLongPressEffect.kt
@@ -189,7 +189,6 @@
durations?.get(1) ?: LongPressHapticBuilder.INVALID_DURATION,
effectDuration
)
- _postedActionType.value = ActionType.INITIALIZE_ANIMATOR
setState(State.IDLE)
return true
}
@@ -209,6 +208,5 @@
START_ANIMATOR,
REVERSE_ANIMATOR,
CANCEL_ANIMATOR,
- INITIALIZE_ANIMATOR,
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/haptics/qs/QSLongPressEffectViewBinder.kt b/packages/SystemUI/src/com/android/systemui/haptics/qs/QSLongPressEffectViewBinder.kt
index c591af2..4875f48 100644
--- a/packages/SystemUI/src/com/android/systemui/haptics/qs/QSLongPressEffectViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/haptics/qs/QSLongPressEffectViewBinder.kt
@@ -30,6 +30,7 @@
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.qs.tileimpl.QSTileViewImpl
import kotlinx.coroutines.DisposableHandle
+import kotlinx.coroutines.flow.filterNotNull
object QSLongPressEffectViewBinder {
@@ -49,39 +50,24 @@
launch({ "${tileSpec ?: "unknownTileSpec"}#LongPressEffect#action" }) {
var effectAnimator: ValueAnimator? = null
- qsLongPressEffect.actionType.collect { action ->
- action?.let {
- when (it) {
- QSLongPressEffect.ActionType.CLICK -> {
- tile.performClick()
- qsLongPressEffect.clearActionType()
- }
- QSLongPressEffect.ActionType.LONG_PRESS -> {
- tile.performLongClick()
- qsLongPressEffect.clearActionType()
- }
- QSLongPressEffect.ActionType.RESET_AND_LONG_PRESS -> {
- tile.resetLongPressEffectProperties()
- tile.performLongClick()
- qsLongPressEffect.clearActionType()
- }
- QSLongPressEffect.ActionType.START_ANIMATOR -> {
- if (effectAnimator?.isRunning == false) {
- effectAnimator?.start()
- }
- }
- QSLongPressEffect.ActionType.REVERSE_ANIMATOR -> {
- effectAnimator?.let {
- val pausedProgress = it.animatedFraction
- qsLongPressEffect.playReverseHaptics(pausedProgress)
- it.reverse()
- }
- }
- QSLongPressEffect.ActionType.CANCEL_ANIMATOR -> {
- tile.resetLongPressEffectProperties()
- effectAnimator?.cancel()
- }
- QSLongPressEffect.ActionType.INITIALIZE_ANIMATOR -> {
+ qsLongPressEffect.actionType.filterNotNull().collect { action ->
+ when (action) {
+ QSLongPressEffect.ActionType.CLICK -> {
+ tile.performClick()
+ qsLongPressEffect.clearActionType()
+ }
+ QSLongPressEffect.ActionType.LONG_PRESS -> {
+ tile.prepareForLaunch()
+ tile.performLongClick()
+ qsLongPressEffect.clearActionType()
+ }
+ QSLongPressEffect.ActionType.RESET_AND_LONG_PRESS -> {
+ tile.resetLongPressEffectProperties()
+ tile.performLongClick()
+ qsLongPressEffect.clearActionType()
+ }
+ QSLongPressEffect.ActionType.START_ANIMATOR -> {
+ if (effectAnimator?.isRunning != true) {
effectAnimator =
ValueAnimator.ofFloat(0f, 1f).apply {
this.duration =
@@ -99,9 +85,21 @@
}
doOnEnd { qsLongPressEffect.handleAnimationComplete() }
doOnCancel { qsLongPressEffect.handleAnimationCancel() }
+ start()
}
}
}
+ QSLongPressEffect.ActionType.REVERSE_ANIMATOR -> {
+ effectAnimator?.let {
+ val pausedProgress = it.animatedFraction
+ qsLongPressEffect.playReverseHaptics(pausedProgress)
+ it.reverse()
+ }
+ }
+ QSLongPressEffect.ActionType.CANCEL_ANIMATOR -> {
+ tile.resetLongPressEffectProperties()
+ effectAnimator?.cancel()
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardModule.kt b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardModule.kt
index c6fb4f9..fc9406b 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardModule.kt
@@ -19,12 +19,13 @@
import com.android.systemui.keyboard.data.repository.KeyboardRepository
import com.android.systemui.keyboard.data.repository.KeyboardRepositoryImpl
+import com.android.systemui.keyboard.shortcut.ShortcutHelperModule
import com.android.systemui.keyboard.stickykeys.data.repository.StickyKeysRepository
import com.android.systemui.keyboard.stickykeys.data.repository.StickyKeysRepositoryImpl
import dagger.Binds
import dagger.Module
-@Module
+@Module(includes = [ShortcutHelperModule::class])
abstract class KeyboardModule {
@Binds
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ShortcutHelperModule.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ShortcutHelperModule.kt
new file mode 100644
index 0000000..5635f80
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ShortcutHelperModule.kt
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyboard.shortcut
+
+import android.app.Activity
+import com.android.systemui.CoreStartable
+import com.android.systemui.Flags.keyboardShortcutHelperRewrite
+import com.android.systemui.keyboard.shortcut.data.repository.ShortcutHelperRepository
+import com.android.systemui.keyboard.shortcut.ui.ShortcutHelperActivityStarter
+import com.android.systemui.keyboard.shortcut.ui.view.ShortcutHelperActivity
+import dagger.Binds
+import dagger.Lazy
+import dagger.Module
+import dagger.Provides
+import dagger.multibindings.ClassKey
+import dagger.multibindings.IntoMap
+
+@Module
+interface ShortcutHelperModule {
+
+ @Binds
+ @IntoMap
+ @ClassKey(ShortcutHelperActivity::class)
+ fun activity(impl: ShortcutHelperActivity): Activity
+
+ companion object {
+ @Provides
+ @IntoMap
+ @ClassKey(ShortcutHelperActivityStarter::class)
+ fun starter(implLazy: Lazy<ShortcutHelperActivityStarter>): CoreStartable {
+ return if (keyboardShortcutHelperRewrite()) {
+ implLazy.get()
+ } else {
+ // No-op implementation when the flag is disabled.
+ NoOpStartable
+ }
+ }
+
+ @Provides
+ @IntoMap
+ @ClassKey(ShortcutHelperRepository::class)
+ fun repo(implLazy: Lazy<ShortcutHelperRepository>): CoreStartable {
+ return if (keyboardShortcutHelperRewrite()) {
+ implLazy.get()
+ } else {
+ // No-op implementation when the flag is disabled.
+ NoOpStartable
+ }
+ }
+ }
+}
+
+private object NoOpStartable : CoreStartable {
+ override fun start() {}
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/ShortcutHelperRepository.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/ShortcutHelperRepository.kt
new file mode 100644
index 0000000..9450af4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/ShortcutHelperRepository.kt
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyboard.shortcut.data.repository
+
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.content.IntentFilter
+import com.android.systemui.CoreStartable
+import com.android.systemui.broadcast.BroadcastDispatcher
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyboard.shortcut.shared.model.ShortcutHelperState
+import com.android.systemui.keyboard.shortcut.shared.model.ShortcutHelperState.Active
+import com.android.systemui.keyboard.shortcut.shared.model.ShortcutHelperState.Inactive
+import com.android.systemui.statusbar.CommandQueue
+import javax.inject.Inject
+import kotlinx.coroutines.flow.MutableStateFlow
+
+@SysUISingleton
+class ShortcutHelperRepository
+@Inject
+constructor(
+ private val commandQueue: CommandQueue,
+ private val broadcastDispatcher: BroadcastDispatcher,
+) : CoreStartable {
+
+ val state = MutableStateFlow<ShortcutHelperState>(Inactive)
+
+ override fun start() {
+ registerBroadcastReceiver(
+ action = Intent.ACTION_SHOW_KEYBOARD_SHORTCUTS,
+ onReceive = { state.value = Active() }
+ )
+ registerBroadcastReceiver(
+ action = Intent.ACTION_DISMISS_KEYBOARD_SHORTCUTS,
+ onReceive = { state.value = Inactive }
+ )
+ commandQueue.addCallback(
+ object : CommandQueue.Callbacks {
+ override fun dismissKeyboardShortcutsMenu() {
+ state.value = Inactive
+ }
+
+ override fun toggleKeyboardShortcutsMenu(deviceId: Int) {
+ state.value =
+ if (state.value is Inactive) {
+ Active(deviceId)
+ } else {
+ Inactive
+ }
+ }
+ }
+ )
+ }
+
+ fun hide() {
+ state.value = Inactive
+ }
+
+ private fun registerBroadcastReceiver(action: String, onReceive: () -> Unit) {
+ broadcastDispatcher.registerReceiver(
+ receiver =
+ object : BroadcastReceiver() {
+ override fun onReceive(context: Context, intent: Intent) {
+ onReceive()
+ }
+ },
+ filter = IntentFilter(action),
+ flags = Context.RECEIVER_EXPORTED or Context.RECEIVER_VISIBLE_TO_INSTANT_APPS
+ )
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/domain/interactor/ShortcutHelperInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/domain/interactor/ShortcutHelperInteractor.kt
new file mode 100644
index 0000000..d3f7e24
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/domain/interactor/ShortcutHelperInteractor.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyboard.shortcut.domain.interactor
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyboard.shortcut.data.repository.ShortcutHelperRepository
+import com.android.systemui.keyboard.shortcut.shared.model.ShortcutHelperState
+import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+
+@SysUISingleton
+class ShortcutHelperInteractor
+@Inject
+constructor(private val repository: ShortcutHelperRepository) {
+
+ val state: Flow<ShortcutHelperState> = repository.state
+
+ fun onUserLeave() {
+ repository.hide()
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/shared/model/GridLayoutTypeKey.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/shared/model/ShortcutHelperState.kt
similarity index 63%
copy from packages/SystemUI/src/com/android/systemui/qs/panels/shared/model/GridLayoutTypeKey.kt
copy to packages/SystemUI/src/com/android/systemui/keyboard/shortcut/shared/model/ShortcutHelperState.kt
index 0dbaaba..d22d6c8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/shared/model/GridLayoutTypeKey.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/shared/model/ShortcutHelperState.kt
@@ -14,15 +14,10 @@
* limitations under the License.
*/
-package com.android.systemui.qs.panels.shared.model
+package com.android.systemui.keyboard.shortcut.shared.model
-import dagger.MapKey
-import kotlin.reflect.KClass
+sealed interface ShortcutHelperState {
+ data object Inactive : ShortcutHelperState
-/**
- * Dagger map key to associate a [GridLayoutType] with its
- * [com.android.systemui.qs.panels.ui.compose.GridLayout].
- */
-@Retention(AnnotationRetention.RUNTIME)
-@MapKey
-annotation class GridLayoutTypeKey(val value: KClass<out GridLayoutType>)
+ data class Active(val deviceId: Int? = null) : ShortcutHelperState
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/ShortcutHelperActivityStarter.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/ShortcutHelperActivityStarter.kt
new file mode 100644
index 0000000..fbf52e7
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/ShortcutHelperActivityStarter.kt
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyboard.shortcut.ui
+
+import android.content.Context
+import android.content.Intent
+import com.android.systemui.CoreStartable
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.keyboard.shortcut.ui.view.ShortcutHelperActivity
+import com.android.systemui.keyboard.shortcut.ui.viewmodel.ShortcutHelperViewModel
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
+
+@SysUISingleton
+class ShortcutHelperActivityStarter(
+ private val context: Context,
+ @Application private val applicationScope: CoroutineScope,
+ private val viewModel: ShortcutHelperViewModel,
+ private val startActivity: (Intent) -> Unit,
+) : CoreStartable {
+
+ @Inject
+ constructor(
+ context: Context,
+ @Application applicationScope: CoroutineScope,
+ viewModel: ShortcutHelperViewModel,
+ ) : this(
+ context,
+ applicationScope,
+ viewModel,
+ startActivity = { intent -> context.startActivity(intent) }
+ )
+
+ override fun start() {
+ applicationScope.launch {
+ viewModel.shouldShow.collect { shouldShow ->
+ if (shouldShow) {
+ startShortcutHelperActivity()
+ }
+ }
+ }
+ }
+
+ private fun startShortcutHelperActivity() {
+ startActivity(
+ Intent(context, ShortcutHelperActivity::class.java)
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ )
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ShortcutHelperActivity.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/view/ShortcutHelperActivity.kt
similarity index 86%
rename from packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ShortcutHelperActivity.kt
rename to packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/view/ShortcutHelperActivity.kt
index 692fbb0..934f9ee 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ShortcutHelperActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/view/ShortcutHelperActivity.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.keyboard.shortcut
+package com.android.systemui.keyboard.shortcut.ui.view
import android.graphics.Insets
import android.os.Bundle
@@ -24,16 +24,25 @@
import androidx.activity.ComponentActivity
import androidx.activity.OnBackPressedCallback
import androidx.core.view.updatePadding
+import androidx.lifecycle.flowWithLifecycle
+import androidx.lifecycle.lifecycleScope
+import com.android.systemui.keyboard.shortcut.ui.viewmodel.ShortcutHelperViewModel
import com.android.systemui.res.R
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetBehavior.BottomSheetCallback
import com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_HIDDEN
+import javax.inject.Inject
+import kotlinx.coroutines.launch
/**
* Activity that hosts the new version of the keyboard shortcut helper. It will be used both for
* small and large screen devices.
*/
-class ShortcutHelperActivity : ComponentActivity() {
+class ShortcutHelperActivity
+@Inject
+constructor(
+ private val viewModel: ShortcutHelperViewModel,
+) : ComponentActivity() {
private val bottomSheetContainer
get() = requireViewById<View>(R.id.shortcut_helper_sheet_container)
@@ -53,6 +62,24 @@
setUpPredictiveBack()
setUpSheetDismissListener()
setUpDismissOnTouchOutside()
+ observeFinishRequired()
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ if (isFinishing) {
+ viewModel.onUserLeave()
+ }
+ }
+
+ private fun observeFinishRequired() {
+ lifecycleScope.launch {
+ viewModel.shouldShow.flowWithLifecycle(lifecycle).collect { shouldShow ->
+ if (!shouldShow) {
+ finish()
+ }
+ }
+ }
}
private fun setupEdgeToEdge() {
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutHelperViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutHelperViewModel.kt
new file mode 100644
index 0000000..7e48c65
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutHelperViewModel.kt
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyboard.shortcut.ui.viewmodel
+
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.keyboard.shortcut.domain.interactor.ShortcutHelperInteractor
+import com.android.systemui.keyboard.shortcut.shared.model.ShortcutHelperState
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flowOn
+import kotlinx.coroutines.flow.map
+
+class ShortcutHelperViewModel
+@Inject
+constructor(
+ @Background private val backgroundDispatcher: CoroutineDispatcher,
+ private val interactor: ShortcutHelperInteractor
+) {
+
+ val shouldShow =
+ interactor.state
+ .map { it is ShortcutHelperState.Active }
+ .distinctUntilChanged()
+ .flowOn(backgroundDispatcher)
+
+ fun onUserLeave() {
+ interactor.onUserLeave()
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java
index 00ec1a1..44e795c 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java
@@ -187,18 +187,15 @@
return;
}
- // current indication is updated to empty
+ // Current indication is updated to empty.
+ // Update to empty even if `currMsgShownForMinTime` is false.
if (mCurrIndicationType == type
&& !hasNewIndication
&& showAsap) {
- if (currMsgShownForMinTime) {
- if (mShowNextIndicationRunnable != null) {
- mShowNextIndicationRunnable.runImmediately();
- } else {
- showIndication(INDICATION_TYPE_NONE);
- }
+ if (mShowNextIndicationRunnable != null) {
+ mShowNextIndicationRunnable.runImmediately();
} else {
- scheduleShowNextIndication(minShowDuration - timeSinceLastIndicationSwitch);
+ showIndication(INDICATION_TYPE_NONE);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 5d31d1e..d6fd354 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -177,10 +177,6 @@
import com.android.systemui.wallpapers.data.repository.WallpaperRepository;
import com.android.wm.shell.keyguard.KeyguardTransitions;
-import dagger.Lazy;
-
-import kotlinx.coroutines.CoroutineDispatcher;
-
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -190,6 +186,9 @@
import java.util.concurrent.Executor;
import java.util.function.Consumer;
+import dagger.Lazy;
+import kotlinx.coroutines.CoroutineDispatcher;
+
/**
* Mediates requests related to the keyguard. This includes queries about the
* state of the keyguard, power management events that effect whether the keyguard
@@ -1234,7 +1233,7 @@
mUnoccludeAnimator.cancel();
}
- if (isDream || mShowCommunalByDefault) {
+ if (isDream || mShowCommunalWhenUnoccluding) {
initAlphaForAnimationTargets(wallpapers);
if (isDream) {
mDreamViewModel.get().startTransitionFromDream();
@@ -1372,7 +1371,7 @@
private final Lazy<DreamViewModel> mDreamViewModel;
private final Lazy<CommunalTransitionViewModel> mCommunalTransitionViewModel;
private RemoteAnimationTarget mRemoteAnimationTarget;
- private boolean mShowCommunalByDefault = false;
+ private boolean mShowCommunalWhenUnoccluding = false;
private final Lazy<WindowManagerLockscreenVisibilityManager> mWmLockscreenVisibilityManager;
@@ -1630,8 +1629,10 @@
getRemoteSurfaceAlphaApplier());
mJavaAdapter.alwaysCollectFlow(dreamViewModel.getTransitionEnded(),
getFinishedCallbackConsumer());
- mJavaAdapter.alwaysCollectFlow(communalViewModel.getShowByDefault(),
- (showByDefault) -> mShowCommunalByDefault = showByDefault);
+ mJavaAdapter.alwaysCollectFlow(communalViewModel.getShowCommunalFromOccluded(),
+ (showCommunalFromOccluded) -> {
+ mShowCommunalWhenUnoccluding = showCommunalFromOccluded;
+ });
mJavaAdapter.alwaysCollectFlow(communalViewModel.getTransitionFromOccludedEnded(),
getFinishedCallbackConsumer());
}
@@ -3214,6 +3215,10 @@
mHideAnimationRun = false;
adjustStatusBarLocked();
sendUserPresentBroadcast();
+
+ if (!KeyguardWmStateRefactor.isEnabled()) {
+ mKeyguardInteractor.dismissKeyguard();
+ }
}
private Configuration.Builder createInteractionJankMonitorConf(int cuj) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
index 462d837..8a53dd1 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
@@ -17,7 +17,6 @@
package com.android.systemui.keyguard.data.repository
import android.graphics.Point
-import android.hardware.biometrics.BiometricSourceType
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.keyguard.KeyguardUpdateMonitorCallback
import com.android.systemui.biometrics.AuthController
@@ -31,6 +30,7 @@
import com.android.systemui.doze.DozeTransitionCallback
import com.android.systemui.doze.DozeTransitionListener
import com.android.systemui.dreams.DreamOverlayCallbackController
+import com.android.systemui.keyguard.shared.model.BiometricUnlockMode
import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
import com.android.systemui.keyguard.shared.model.BiometricUnlockSource
import com.android.systemui.keyguard.shared.model.DismissAction
@@ -169,10 +169,13 @@
/** Observable for the [StatusBarState] */
val statusBarState: StateFlow<StatusBarState>
- /** Observable for biometric unlock modes */
+ /** Observable for biometric unlock state which includes the mode and unlock source */
val biometricUnlockState: Flow<BiometricUnlockModel>
- fun setBiometricUnlockState(value: BiometricUnlockModel)
+ fun setBiometricUnlockState(
+ unlockMode: BiometricUnlockMode,
+ unlockSource: BiometricUnlockSource?,
+ )
/** Approximate location on the screen of the fingerprint sensor. */
val fingerprintSensorLocation: Flow<Point?>
@@ -180,9 +183,6 @@
/** Approximate location on the screen of the face unlock sensor/front facing camera. */
val faceSensorLocation: Flow<Point?>
- /** Source of the most recent biometric unlock, such as fingerprint or face. */
- val biometricUnlockSource: Flow<BiometricUnlockSource?>
-
/** Whether quick settings or quick-quick settings is visible. */
val isQuickSettingsVisible: Flow<Boolean>
@@ -597,11 +597,15 @@
statusBarStateIntToObject(statusBarStateController.state)
)
- private val _biometricUnlockState = MutableStateFlow(BiometricUnlockModel.NONE)
+ private val _biometricUnlockState: MutableStateFlow<BiometricUnlockModel> =
+ MutableStateFlow(BiometricUnlockModel(BiometricUnlockMode.NONE, null))
override val biometricUnlockState = _biometricUnlockState.asStateFlow()
- override fun setBiometricUnlockState(value: BiometricUnlockModel) {
- _biometricUnlockState.value = value
+ override fun setBiometricUnlockState(
+ unlockMode: BiometricUnlockMode,
+ unlockSource: BiometricUnlockSource?,
+ ) {
+ _biometricUnlockState.value = BiometricUnlockModel(unlockMode, unlockSource)
}
override val fingerprintSensorLocation: Flow<Point?> = conflatedCallbackFlow {
@@ -628,27 +632,6 @@
override val faceSensorLocation: Flow<Point?> = facePropertyRepository.sensorLocation
- override val biometricUnlockSource: Flow<BiometricUnlockSource?> = conflatedCallbackFlow {
- val callback =
- object : KeyguardUpdateMonitorCallback() {
- override fun onBiometricAuthenticated(
- userId: Int,
- biometricSourceType: BiometricSourceType?,
- isStrongBiometric: Boolean
- ) {
- trySendWithFailureLogging(
- BiometricUnlockSource.fromBiometricSourceType(biometricSourceType),
- TAG,
- "onBiometricAuthenticated"
- )
- }
- }
-
- keyguardUpdateMonitor.registerCallback(callback)
- trySendWithFailureLogging(null, TAG, "initial value")
- awaitClose { keyguardUpdateMonitor.removeCallback(callback) }
- }
-
private val _isQuickSettingsVisible = MutableStateFlow(false)
override val isQuickSettingsVisible: Flow<Boolean> = _isQuickSettingsVisible.asStateFlow()
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt
index 6138330..3956901 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt
@@ -76,4 +76,9 @@
@Binds fun trustRepository(impl: TrustRepositoryImpl): TrustRepository
@Binds fun keyguardClockRepository(impl: KeyguardClockRepositoryImpl): KeyguardClockRepository
+
+ @Binds
+ fun keyguardSmartspaceRepository(
+ impl: KeyguardSmartspaceRepositoryImpl
+ ): KeyguardSmartspaceRepository
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardSmartspaceRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardSmartspaceRepository.kt
index afe9151..956125c 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardSmartspaceRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardSmartspaceRepository.kt
@@ -16,19 +16,68 @@
package com.android.systemui.keyguard.data.repository
+import android.content.Context
+import android.provider.Settings
import android.view.View
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.settings.UserTracker
+import com.android.systemui.util.settings.SecureSettings
+import com.android.systemui.util.settings.SettingsProxyExt.observerFlow
import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.onStart
+import kotlinx.coroutines.flow.stateIn
+
+interface KeyguardSmartspaceRepository {
+ val bcSmartspaceVisibility: StateFlow<Int>
+ val isWeatherEnabled: StateFlow<Boolean>
+ fun setBcSmartspaceVisibility(visibility: Int)
+}
@SysUISingleton
-class KeyguardSmartspaceRepository @Inject constructor() {
+class KeyguardSmartspaceRepositoryImpl
+@Inject
+constructor(
+ context: Context,
+ private val secureSettings: SecureSettings,
+ private val userTracker: UserTracker,
+ @Application private val applicationScope: CoroutineScope,
+) : KeyguardSmartspaceRepository {
private val _bcSmartspaceVisibility: MutableStateFlow<Int> = MutableStateFlow(View.GONE)
- val bcSmartspaceVisibility: StateFlow<Int> = _bcSmartspaceVisibility.asStateFlow()
+ override val bcSmartspaceVisibility: StateFlow<Int> = _bcSmartspaceVisibility.asStateFlow()
+ val defaultValue =
+ context.resources.getBoolean(
+ com.android.internal.R.bool.config_lockscreenWeatherEnabledByDefault
+ )
+ override val isWeatherEnabled: StateFlow<Boolean> =
+ secureSettings
+ .observerFlow(
+ names = arrayOf(Settings.Secure.LOCK_SCREEN_WEATHER_ENABLED),
+ userId = userTracker.userId,
+ )
+ .onStart { emit(Unit) }
+ .map { getLockscreenWeatherEnabled() }
+ .stateIn(
+ scope = applicationScope,
+ started = SharingStarted.WhileSubscribed(),
+ initialValue = getLockscreenWeatherEnabled()
+ )
- fun setBcSmartspaceVisibility(visibility: Int) {
+ override fun setBcSmartspaceVisibility(visibility: Int) {
_bcSmartspaceVisibility.value = visibility
}
+
+ private fun getLockscreenWeatherEnabled(): Boolean {
+ return secureSettings.getIntForUser(
+ Settings.Secure.LOCK_SCREEN_WEATHER_ENABLED,
+ if (defaultValue) 1 else 0,
+ userTracker.userId
+ ) == 1
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt
index 4c54bfd..e32bfcf 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt
@@ -89,6 +89,12 @@
suspend fun startTransition(info: TransitionInfo): UUID?
/**
+ * Emits STARTED and FINISHED transition steps to the given state. This is used during boot to
+ * seed the repository with the appropriate initial state.
+ */
+ suspend fun emitInitialStepsFromOff(to: KeyguardState)
+
+ /**
* Allows manual control of a transition. When calling [startTransition], the consumer must pass
* in a null animator. In return, it will get a unique [UUID] that will be validated to allow
* further updates.
@@ -141,9 +147,17 @@
private var updateTransitionId: UUID? = null
init {
- // Seed with transitions signaling a boot into lockscreen state. If updating this, please
- // also update FakeKeyguardTransitionRepository.
- initialTransitionSteps.forEach(::emitTransition)
+ // Start with a FINISHED transition in OFF. KeyguardBootInteractor will transition from OFF
+ // to either GONE or LOCKSCREEN once we're booted up and can determine which state we should
+ // start in.
+ emitTransition(
+ TransitionStep(
+ KeyguardState.OFF,
+ KeyguardState.OFF,
+ 1f,
+ TransitionState.FINISHED,
+ )
+ )
}
override suspend fun startTransition(info: TransitionInfo): UUID? {
@@ -251,6 +265,28 @@
lastStep = nextStep
}
+ override suspend fun emitInitialStepsFromOff(to: KeyguardState) {
+ emitTransition(
+ TransitionStep(
+ KeyguardState.OFF,
+ to,
+ 0f,
+ TransitionState.STARTED,
+ ownerName = "KeyguardTransitionRepository(boot)",
+ )
+ )
+
+ emitTransition(
+ TransitionStep(
+ KeyguardState.OFF,
+ to,
+ 1f,
+ TransitionState.FINISHED,
+ ownerName = "KeyguardTransitionRepository(boot)",
+ ),
+ )
+ }
+
private fun logAndTrace(step: TransitionStep, isManual: Boolean) {
if (step.transitionState == TransitionState.RUNNING) {
return
@@ -271,31 +307,5 @@
companion object {
private const val TAG = "KeyguardTransitionRepository"
-
- /**
- * Transition steps to seed the repository with, so that all of the transition interactor
- * flows emit reasonable initial values.
- */
- val initialTransitionSteps: List<TransitionStep> =
- listOf(
- TransitionStep(
- KeyguardState.OFF,
- KeyguardState.OFF,
- 1f,
- TransitionState.FINISHED,
- ),
- TransitionStep(
- KeyguardState.OFF,
- KeyguardState.LOCKSCREEN,
- 0f,
- TransitionState.STARTED,
- ),
- TransitionStep(
- KeyguardState.OFF,
- KeyguardState.LOCKSCREEN,
- 1f,
- TransitionState.FINISHED,
- ),
- )
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepository.kt
index eac476f..0a15bbf 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepository.kt
@@ -24,7 +24,7 @@
import androidx.core.animation.ValueAnimator
import com.android.keyguard.logging.ScrimLogger
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
+import com.android.systemui.keyguard.shared.model.BiometricUnlockMode
import com.android.systemui.keyguard.shared.model.BiometricUnlockSource
import com.android.systemui.power.data.repository.PowerRepository
import com.android.systemui.power.shared.model.WakeSleepReason
@@ -40,7 +40,6 @@
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
-import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
@@ -83,7 +82,7 @@
}
/** The reveal effect used if the device was locked/unlocked via the power button. */
- private val powerButtonRevealEffect: Flow<LightRevealEffect?> =
+ private val powerButtonRevealEffect: Flow<LightRevealEffect> =
flowOf(
PowerButtonReveal(
context.resources
@@ -92,42 +91,31 @@
)
)
- private val tapRevealEffect: Flow<LightRevealEffect?> =
+ private val tapRevealEffect: Flow<LightRevealEffect> =
keyguardRepository.lastDozeTapToWakePosition.map {
- it?.let { constructCircleRevealFromPoint(it) }
+ it?.let { constructCircleRevealFromPoint(it) } ?: DEFAULT_REVEAL_EFFECT
}
/**
* Reveal effect to use for a fingerprint unlock. This is reconstructed if the fingerprint
* sensor location on the screen (in pixels) changes due to configuration changes.
*/
- private val fingerprintRevealEffect: Flow<LightRevealEffect?> =
+ private val fingerprintRevealEffect: Flow<LightRevealEffect> =
keyguardRepository.fingerprintSensorLocation.map {
- it?.let { constructCircleRevealFromPoint(it) }
+ it?.let { constructCircleRevealFromPoint(it) } ?: DEFAULT_REVEAL_EFFECT
}
/**
* Reveal effect to use for a face unlock. This is reconstructed if the face sensor/front camera
* location on the screen (in pixels) changes due to configuration changes.
*/
- private val faceRevealEffect: Flow<LightRevealEffect?> =
- keyguardRepository.faceSensorLocation.map { it?.let { constructCircleRevealFromPoint(it) } }
-
- /**
- * The reveal effect we'll use for the next biometric unlock animation. We switch between the
- * fingerprint/face unlock effect flows depending on the biometric unlock source.
- */
- private val biometricRevealEffect: Flow<LightRevealEffect?> =
- keyguardRepository.biometricUnlockSource.flatMapLatest { source ->
- when (source) {
- BiometricUnlockSource.FINGERPRINT_SENSOR -> fingerprintRevealEffect
- BiometricUnlockSource.FACE_SENSOR -> faceRevealEffect
- else -> flowOf(null)
- }
+ private val faceRevealEffect: Flow<LightRevealEffect> =
+ keyguardRepository.faceSensorLocation.map {
+ it?.let { constructCircleRevealFromPoint(it) } ?: DEFAULT_REVEAL_EFFECT
}
/** The reveal effect we'll use for the next non-biometric unlock (tap, power button, etc). */
- private val nonBiometricRevealEffect: Flow<LightRevealEffect?> =
+ private val nonBiometricRevealEffect: Flow<LightRevealEffect> =
powerRepository.wakefulness.flatMapLatest { wakefulnessModel ->
when {
wakefulnessModel.isAwakeOrAsleepFrom(WakeSleepReason.POWER_BUTTON) ->
@@ -169,29 +157,22 @@
scrimLogger.d(TAG, "startRevealAmountAnimator, reveal", reveal)
}
- override val revealEffect =
- combine(
- keyguardRepository.biometricUnlockState,
- biometricRevealEffect,
- nonBiometricRevealEffect
- ) { biometricUnlockState, biometricReveal, nonBiometricReveal ->
-
+ override val revealEffect: Flow<LightRevealEffect> =
+ keyguardRepository.biometricUnlockState
+ .flatMapLatest { biometricUnlockState ->
// Use the biometric reveal for any flavor of wake and unlocking.
- val revealEffect =
- when (biometricUnlockState) {
- BiometricUnlockModel.WAKE_AND_UNLOCK,
- BiometricUnlockModel.WAKE_AND_UNLOCK_PULSING,
- BiometricUnlockModel.WAKE_AND_UNLOCK_FROM_DREAM -> biometricReveal
- else -> nonBiometricReveal
+ when (biometricUnlockState.mode) {
+ BiometricUnlockMode.WAKE_AND_UNLOCK,
+ BiometricUnlockMode.WAKE_AND_UNLOCK_PULSING,
+ BiometricUnlockMode.WAKE_AND_UNLOCK_FROM_DREAM -> {
+ if (biometricUnlockState.source == BiometricUnlockSource.FACE_SENSOR) {
+ faceRevealEffect
+ } else {
+ fingerprintRevealEffect
+ }
}
- ?: DEFAULT_REVEAL_EFFECT
-
- scrimLogger.d(
- TAG,
- "revealEffect",
- "$revealEffect, biometricUnlockState: ${biometricUnlockState.name}"
- )
- return@combine revealEffect
+ else -> nonBiometricRevealEffect
+ }
}
.distinctUntilChanged()
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/BiometricUnlockInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/BiometricUnlockInteractor.kt
index cb003a7..576fafd 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/BiometricUnlockInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/BiometricUnlockInteractor.kt
@@ -2,7 +2,8 @@
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.data.repository.KeyguardRepository
-import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
+import com.android.systemui.keyguard.shared.model.BiometricUnlockMode
+import com.android.systemui.keyguard.shared.model.BiometricUnlockSource
import com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_DISMISS_BOUNCER
import com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_NONE
import com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_ONLY_WAKE
@@ -13,7 +14,9 @@
import com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING
import com.android.systemui.statusbar.phone.BiometricUnlockController.WakeAndUnlockMode
import javax.inject.Inject
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+@ExperimentalCoroutinesApi
@SysUISingleton
class BiometricUnlockInteractor
@Inject
@@ -21,21 +24,24 @@
private val keyguardRepository: KeyguardRepository,
) {
- fun setBiometricUnlockState(@WakeAndUnlockMode unlockStateInt: Int) {
+ fun setBiometricUnlockState(
+ @WakeAndUnlockMode unlockStateInt: Int,
+ biometricUnlockSource: BiometricUnlockSource?,
+ ) {
val state = biometricModeIntToObject(unlockStateInt)
- keyguardRepository.setBiometricUnlockState(state)
+ keyguardRepository.setBiometricUnlockState(state, biometricUnlockSource)
}
- private fun biometricModeIntToObject(@WakeAndUnlockMode value: Int): BiometricUnlockModel {
+ private fun biometricModeIntToObject(@WakeAndUnlockMode value: Int): BiometricUnlockMode {
return when (value) {
- MODE_NONE -> BiometricUnlockModel.NONE
- MODE_WAKE_AND_UNLOCK -> BiometricUnlockModel.WAKE_AND_UNLOCK
- MODE_WAKE_AND_UNLOCK_PULSING -> BiometricUnlockModel.WAKE_AND_UNLOCK_PULSING
- MODE_SHOW_BOUNCER -> BiometricUnlockModel.SHOW_BOUNCER
- MODE_ONLY_WAKE -> BiometricUnlockModel.ONLY_WAKE
- MODE_UNLOCK_COLLAPSING -> BiometricUnlockModel.UNLOCK_COLLAPSING
- MODE_WAKE_AND_UNLOCK_FROM_DREAM -> BiometricUnlockModel.WAKE_AND_UNLOCK_FROM_DREAM
- MODE_DISMISS_BOUNCER -> BiometricUnlockModel.DISMISS_BOUNCER
+ MODE_NONE -> BiometricUnlockMode.NONE
+ MODE_WAKE_AND_UNLOCK -> BiometricUnlockMode.WAKE_AND_UNLOCK
+ MODE_WAKE_AND_UNLOCK_PULSING -> BiometricUnlockMode.WAKE_AND_UNLOCK_PULSING
+ MODE_SHOW_BOUNCER -> BiometricUnlockMode.SHOW_BOUNCER
+ MODE_ONLY_WAKE -> BiometricUnlockMode.ONLY_WAKE
+ MODE_UNLOCK_COLLAPSING -> BiometricUnlockMode.UNLOCK_COLLAPSING
+ MODE_WAKE_AND_UNLOCK_FROM_DREAM -> BiometricUnlockMode.WAKE_AND_UNLOCK_FROM_DREAM
+ MODE_DISMISS_BOUNCER -> BiometricUnlockMode.DISMISS_BOUNCER
else -> throw IllegalArgumentException("Invalid BiometricUnlockModel value: $value")
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt
index c2843d8..4d73774 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt
@@ -24,7 +24,7 @@
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.keyguard.KeyguardWmStateRefactor
import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
-import com.android.systemui.keyguard.shared.model.BiometricUnlockModel.Companion.isWakeAndUnlock
+import com.android.systemui.keyguard.shared.model.BiometricUnlockMode.Companion.isWakeAndUnlock
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionModeOnCanceled
import com.android.systemui.power.domain.interactor.PowerInteractor
@@ -72,7 +72,8 @@
keyguardInteractor.isKeyguardDismissible,
keyguardInteractor.biometricUnlockState,
) { isKeyguardShowing, isKeyguardDismissible, biometricUnlockState ->
- (isWakeAndUnlock(biometricUnlockState) || (!isKeyguardShowing && isKeyguardDismissible))
+ (isWakeAndUnlock(biometricUnlockState.mode) ||
+ (!isKeyguardShowing && isKeyguardDismissible))
}
/**
@@ -110,11 +111,11 @@
// receiving a call to #dismissAod() shortly when the authentication
// completes.
!maybeStartTransitionToOccludedOrInsecureCamera() &&
- !isWakeAndUnlock(biometricUnlockState) &&
+ !isWakeAndUnlock(biometricUnlockState.mode) &&
!primaryBouncerShowing
} else {
!isKeyguardOccludedLegacy &&
- !isWakeAndUnlock(biometricUnlockState) &&
+ !isWakeAndUnlock(biometricUnlockState.mode) &&
!primaryBouncerShowing
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt
index ca7fc66..115fc36 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt
@@ -24,7 +24,7 @@
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.keyguard.KeyguardWmStateRefactor
import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
-import com.android.systemui.keyguard.shared.model.BiometricUnlockModel.Companion.isWakeAndUnlock
+import com.android.systemui.keyguard.shared.model.BiometricUnlockMode.Companion.isWakeAndUnlock
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.power.domain.interactor.PowerInteractor
import com.android.systemui.util.kotlin.Utils.Companion.sample
@@ -66,7 +66,7 @@
listenForTransitionToCamera(scope, keyguardInteractor)
}
- private val canDismissLockScreen: Flow<Boolean> =
+ private val canTransitionToGoneOnWake: Flow<Boolean> =
combine(
keyguardInteractor.isKeyguardShowing,
keyguardInteractor.isKeyguardDismissible,
@@ -87,7 +87,7 @@
keyguardInteractor.biometricUnlockState,
keyguardInteractor.isKeyguardOccluded,
communalInteractor.isIdleOnCommunal,
- canDismissLockScreen,
+ canTransitionToGoneOnWake,
keyguardInteractor.primaryBouncerShowing,
)
.collect {
@@ -96,12 +96,12 @@
biometricUnlockState,
occluded,
isIdleOnCommunal,
- canDismissLockScreen,
+ canTransitionToGoneOnWake,
primaryBouncerShowing) ->
startTransitionTo(
- if (isWakeAndUnlock(biometricUnlockState)) {
+ if (isWakeAndUnlock(biometricUnlockState.mode)) {
KeyguardState.GONE
- } else if (canDismissLockScreen) {
+ } else if (canTransitionToGoneOnWake) {
KeyguardState.GONE
} else if (primaryBouncerShowing) {
KeyguardState.PRIMARY_BOUNCER
@@ -129,7 +129,7 @@
.sample(
communalInteractor.isIdleOnCommunal,
keyguardInteractor.biometricUnlockState,
- canDismissLockScreen,
+ canTransitionToGoneOnWake,
keyguardInteractor.primaryBouncerShowing,
)
.collect {
@@ -142,7 +142,7 @@
if (
!maybeStartTransitionToOccludedOrInsecureCamera() &&
// Handled by dismissFromDozing().
- !isWakeAndUnlock(biometricUnlockState)
+ !isWakeAndUnlock(biometricUnlockState.mode)
) {
startTransitionTo(
if (canDismissLockscreen) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingLockscreenHostedTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingLockscreenHostedTransitionInteractor.kt
index 10d1e15..e738ea4 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingLockscreenHostedTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingLockscreenHostedTransitionInteractor.kt
@@ -22,7 +22,7 @@
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
-import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
+import com.android.systemui.keyguard.shared.model.BiometricUnlockMode
import com.android.systemui.keyguard.shared.model.DozeStateModel
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.power.domain.interactor.PowerInteractor
@@ -104,7 +104,7 @@
scope.launch {
keyguardInteractor.biometricUnlockState
.filterRelevantKeyguardStateAnd { biometricUnlockState ->
- biometricUnlockState == BiometricUnlockModel.WAKE_AND_UNLOCK_FROM_DREAM
+ biometricUnlockState.mode == BiometricUnlockMode.WAKE_AND_UNLOCK_FROM_DREAM
}
.collect { startTransitionTo(KeyguardState.GONE) }
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt
index 69c2c78d..c952e08 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt
@@ -25,7 +25,7 @@
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.keyguard.KeyguardWmStateRefactor
import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
-import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
+import com.android.systemui.keyguard.shared.model.BiometricUnlockMode
import com.android.systemui.keyguard.shared.model.DozeStateModel
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.power.domain.interactor.PowerInteractor
@@ -193,7 +193,7 @@
scope.launch {
keyguardInteractor.biometricUnlockState
.filterRelevantKeyguardStateAnd { biometricUnlockState ->
- biometricUnlockState == BiometricUnlockModel.WAKE_AND_UNLOCK_FROM_DREAM
+ biometricUnlockState.mode == BiometricUnlockMode.WAKE_AND_UNLOCK_FROM_DREAM
}
.collect { startTransitionTo(KeyguardState.GONE) }
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt
index 54d9a78..faab033 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt
@@ -28,7 +28,7 @@
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionModeOnCanceled
import com.android.systemui.power.domain.interactor.PowerInteractor
-import com.android.systemui.util.kotlin.BooleanFlowOperators.and
+import com.android.systemui.util.kotlin.BooleanFlowOperators.allOf
import com.android.systemui.util.kotlin.BooleanFlowOperators.not
import javax.inject.Inject
import kotlin.time.Duration.Companion.seconds
@@ -148,7 +148,7 @@
}
} else {
scope.launch {
- and(keyguardInteractor.isKeyguardOccluded, not(keyguardInteractor.isDreaming))
+ allOf(keyguardInteractor.isKeyguardOccluded, not(keyguardInteractor.isDreaming))
.filterRelevantKeyguardStateAnd { isOccludedAndNotDreaming ->
isOccludedAndNotDreaming
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractor.kt
index ee589f4..e51ba83 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractor.kt
@@ -87,12 +87,15 @@
scope.launch {
keyguardOcclusionInteractor.isShowWhenLockedActivityOnTop
.filterRelevantKeyguardStateAnd { onTop -> !onTop }
- .sample(communalInteractor.isIdleOnCommunal, communalInteractor.showByDefault)
- .collect { (_, isIdleOnCommunal, showCommunalByDefault) ->
+ .sample(
+ communalInteractor.isIdleOnCommunal,
+ communalInteractor.showCommunalFromOccluded,
+ )
+ .collect { (_, isIdleOnCommunal, showCommunalFromOccluded) ->
// Occlusion signals come from the framework, and should interrupt any
// existing transition
val to =
- if (isIdleOnCommunal || showCommunalByDefault) {
+ if (isIdleOnCommunal || showCommunalFromOccluded) {
KeyguardState.GLANCEABLE_HUB
} else {
KeyguardState.LOCKSCREEN
@@ -106,16 +109,16 @@
.sample(
keyguardInteractor.isKeyguardShowing,
communalInteractor.isIdleOnCommunal,
- communalInteractor.showByDefault,
+ communalInteractor.showCommunalFromOccluded,
)
.filterRelevantKeyguardStateAnd { (isOccluded, isShowing, _, _) ->
!isOccluded && isShowing
}
- .collect { (_, _, isIdleOnCommunal, showCommunalByDefault) ->
+ .collect { (_, _, isIdleOnCommunal, showCommunalFromOccluded) ->
// Occlusion signals come from the framework, and should interrupt any
// existing transition
val to =
- if (isIdleOnCommunal || showCommunalByDefault) {
+ if (isIdleOnCommunal || showCommunalFromOccluded) {
KeyguardState.GLANCEABLE_HUB
} else {
KeyguardState.LOCKSCREEN
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
index d191768..88367f4 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
@@ -33,7 +33,6 @@
import com.android.systemui.keyguard.MigrateClocksToBlueprint
import com.android.systemui.keyguard.data.repository.KeyguardRepository
import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
-import com.android.systemui.keyguard.shared.model.BiometricUnlockSource
import com.android.systemui.keyguard.shared.model.CameraLaunchSourceModel
import com.android.systemui.keyguard.shared.model.DozeStateModel
import com.android.systemui.keyguard.shared.model.DozeStateModel.Companion.isDozeOff
@@ -90,6 +89,7 @@
keyguardTransitionInteractor: KeyguardTransitionInteractor,
sceneInteractorProvider: Provider<SceneInteractor>,
private val fromGoneTransitionInteractor: Provider<FromGoneTransitionInteractor>,
+ private val fromLockscreenTransitionInteractor: Provider<FromLockscreenTransitionInteractor>,
sharedNotificationContainerInteractor: Provider<SharedNotificationContainerInteractor>,
@Application applicationScope: CoroutineScope,
) {
@@ -234,13 +234,7 @@
/** Observable for the [StatusBarState] */
val statusBarState: Flow<StatusBarState> = repository.statusBarState
- /** Source of the most recent biometric unlock, such as fingerprint or face. */
- val biometricUnlockSource: Flow<BiometricUnlockSource?> = repository.biometricUnlockSource
-
- /**
- * Observable for [BiometricUnlockModel] when biometrics like face or any fingerprint (rear,
- * side, under display) is used to unlock the device.
- */
+ /** Observable for [BiometricUnlockModel] when biometrics are used to unlock the device. */
val biometricUnlockState: Flow<BiometricUnlockModel> = repository.biometricUnlockState
/** Keyguard is present and is not occluded. */
@@ -307,19 +301,27 @@
configurationInteractor
.dimensionPixelSize(R.dimen.keyguard_translate_distance_on_swipe_up)
.flatMapLatest { translationDistance ->
- combine(
+ combineTransform(
shadeRepository.legacyShadeExpansion.onStart { emit(0f) },
keyguardTransitionInteractor.transitionValue(GONE).onStart { emit(0f) },
) { legacyShadeExpansion, goneValue ->
- if (goneValue == 1f || legacyShadeExpansion == 0f) {
+ if (goneValue == 1f || (goneValue == 0f && legacyShadeExpansion == 0f)) {
// Reset the translation value
- 0f
- } else {
- // On swipe up, translate the keyguard to reveal the bouncer
- MathUtils.lerp(
- translationDistance,
- 0,
- Interpolators.FAST_OUT_LINEAR_IN.getInterpolation(legacyShadeExpansion)
+ emit(0f)
+ } else if (legacyShadeExpansion > 0f && legacyShadeExpansion < 1f) {
+ // On swipe up, translate the keyguard to reveal the bouncer, OR a GONE
+ // transition is running, which means this is a swipe to dismiss. Values of
+ // 0f and 1f need to be ignored in the legacy shade expansion. These can
+ // flip arbitrarily as the legacy shade is reset, and would cause the
+ // translation value to jump around unexpectedly.
+ emit(
+ MathUtils.lerp(
+ translationDistance,
+ 0,
+ Interpolators.FAST_OUT_LINEAR_IN.getInterpolation(
+ legacyShadeExpansion
+ ),
+ )
)
}
}
@@ -417,6 +419,11 @@
fromGoneTransitionInteractor.get().showKeyguard()
}
+ /** Temporary shim, until [KeyguardWmStateRefactor] is enabled */
+ fun dismissKeyguard() {
+ fromLockscreenTransitionInteractor.get().dismissKeyguard()
+ }
+
companion object {
private const val TAG = "KeyguardInteractor"
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt
index 1e3eac8..ccce3bf 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt
@@ -113,7 +113,8 @@
.transitionState
.map {
when (it) {
- is ObservableTransitionState.Idle -> it.scene == Scenes.Lockscreen
+ is ObservableTransitionState.Idle ->
+ it.currentScene == Scenes.Lockscreen
is ObservableTransitionState.Transition ->
it.fromScene == Scenes.Lockscreen || it.toScene == Scenes.Lockscreen
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardSmartspaceInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardSmartspaceInteractor.kt
index bb633b5..45a4b70a2 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardSmartspaceInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardSmartspaceInteractor.kt
@@ -28,6 +28,7 @@
private val keyguardSmartspaceRepository: KeyguardSmartspaceRepository,
) {
val bcSmartspaceVisibility: StateFlow<Int> = keyguardSmartspaceRepository.bcSmartspaceVisibility
+ val isWeatherEnabled: StateFlow<Boolean> = keyguardSmartspaceRepository.isWeatherEnabled
fun setBcSmartspaceVisibility(visibility: Int) {
keyguardSmartspaceRepository.setBcSmartspaceVisibility(visibility)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardSurfaceBehindInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardSurfaceBehindInteractor.kt
index 20b7b2a..82255a0 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardSurfaceBehindInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardSurfaceBehindInteractor.kt
@@ -31,6 +31,7 @@
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.onStart
/**
* Distance over which the surface behind the keyguard is animated in during a Y-translation
@@ -102,8 +103,11 @@
*/
private val isNotificationLaunchAnimationRunningOnKeyguard =
notificationLaunchInteractor.isLaunchAnimationRunning
- .sample(transitionInteractor.finishedKeyguardState)
- .map { it != KeyguardState.GONE }
+ .sample(transitionInteractor.finishedKeyguardState, ::Pair)
+ .map { (animationRunning, finishedState) ->
+ animationRunning && finishedState != KeyguardState.GONE
+ }
+ .onStart { emit(false) }
/**
* Whether we're animating the surface, or a notification launch animation is running (which
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionBootInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionBootInteractor.kt
new file mode 100644
index 0000000..5ad7762
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionBootInteractor.kt
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.domain.interactor
+
+import android.util.Log
+import com.android.systemui.CoreStartable
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
+import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.statusbar.policy.domain.interactor.DeviceProvisioningInteractor
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.launch
+
+/** Handles initialization of the KeyguardTransitionRepository on boot. */
+@SysUISingleton
+class KeyguardTransitionBootInteractor
+@Inject
+constructor(
+ @Application val scope: CoroutineScope,
+ val deviceEntryInteractor: DeviceEntryInteractor,
+ val deviceProvisioningInteractor: DeviceProvisioningInteractor,
+ val keyguardTransitionInteractor: KeyguardTransitionInteractor,
+ val repository: KeyguardTransitionRepository,
+) : CoreStartable {
+
+ /**
+ * Whether the lockscreen should be showing when the device starts up for the first time. If not
+ * then we'll seed the repository with a transition from OFF -> GONE.
+ */
+ @OptIn(ExperimentalCoroutinesApi::class)
+ private val showLockscreenOnBoot =
+ deviceProvisioningInteractor.isDeviceProvisioned.map { provisioned ->
+ (provisioned || deviceEntryInteractor.isAuthenticationRequired()) &&
+ deviceEntryInteractor.isLockscreenEnabled()
+ }
+
+ override fun start() {
+ scope.launch {
+ val state =
+ if (showLockscreenOnBoot.first()) {
+ KeyguardState.LOCKSCREEN
+ } else {
+ KeyguardState.GONE
+ }
+
+ if (
+ keyguardTransitionInteractor.currentTransitionInfoInternal.value.from !=
+ KeyguardState.OFF
+ ) {
+ Log.e(
+ "KeyguardTransitionInteractor",
+ "showLockscreenOnBoot emitted, but we've already " +
+ "transitioned to a state other than OFF. We'll respect that " +
+ "transition, but this should not happen."
+ )
+ } else {
+ repository.emitInitialStepsFromOff(state)
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionCoreStartable.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionCoreStartable.kt
index 91f8420..31b0bf7 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionCoreStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionCoreStartable.kt
@@ -27,6 +27,7 @@
constructor(
private val interactors: Set<TransitionInteractor>,
private val auditLogger: KeyguardTransitionAuditLogger,
+ private val bootInteractor: KeyguardTransitionBootInteractor,
) : CoreStartable {
override fun start() {
@@ -51,6 +52,7 @@
it.start()
}
auditLogger.start()
+ bootInteractor.start()
}
companion object {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractor.kt
index 8d02e0e..bb2eeb7 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractor.kt
@@ -17,7 +17,7 @@
package com.android.systemui.keyguard.domain.interactor
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
+import com.android.systemui.keyguard.shared.model.BiometricUnlockMode
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.statusbar.notification.domain.interactor.NotificationLaunchAnimationInteractor
@@ -165,7 +165,7 @@
) { isDozing, biometricUnlockState ->
// AOD is visible if we're dozing, unless we are wake and unlocking (where we go
// directly from AOD to unlocked while dozing).
- isDozing && !BiometricUnlockModel.isWakeAndUnlock(biometricUnlockState)
+ isDozing && !BiometricUnlockMode.isWakeAndUnlock(biometricUnlockState.mode)
}
.distinctUntilChanged()
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/BiometricUnlockModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/BiometricUnlockModel.kt
index 2ae5ce1..4c709fb 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/BiometricUnlockModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/BiometricUnlockModel.kt
@@ -15,8 +15,19 @@
*/
package com.android.systemui.keyguard.shared.model
+/**
+ * Model [BiometricUnlockMode] with [BiometricUnlockSource].
+ *
+ * @param source can be null as a starting state or if the unlock isn't coming from a biometric (the
+ * latter should be deprecated in the future, b/338578036)
+ */
+data class BiometricUnlockModel(
+ val mode: BiometricUnlockMode,
+ val source: BiometricUnlockSource?,
+)
+
/** Model device wakefulness states. */
-enum class BiometricUnlockModel {
+enum class BiometricUnlockMode {
/** Mode in which we don't need to wake up the device when we authenticate. */
NONE,
/**
@@ -60,12 +71,12 @@
DISMISS_BOUNCER
)
- fun isWakeAndUnlock(model: BiometricUnlockModel): Boolean {
- return wakeAndUnlockModes.contains(model)
+ fun isWakeAndUnlock(mode: BiometricUnlockMode): Boolean {
+ return wakeAndUnlockModes.contains(mode)
}
- fun dismissesKeyguard(model: BiometricUnlockModel): Boolean {
- return dismissesKeyguardModes.contains(model)
+ fun dismissesKeyguard(mode: BiometricUnlockMode): Boolean {
+ return dismissesKeyguardModes.contains(mode)
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt
index 53f0132..18022a9 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt
@@ -17,6 +17,7 @@
package com.android.systemui.keyguard.ui.binder
import android.graphics.PixelFormat
+import android.util.Log
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
@@ -95,11 +96,11 @@
applicationScope.launch("$TAG#alternateBouncerWindowViewModel") {
alternateBouncerWindowViewModel.get().alternateBouncerWindowRequired.collect {
addAlternateBouncerWindowView ->
+ Log.d(TAG, "alternateBouncerWindowRequired=$addAlternateBouncerWindowView")
if (addAlternateBouncerWindowView) {
addViewToWindowManager()
- val scrim =
+ val scrim: ScrimView =
alternateBouncerView!!.requireViewById(R.id.alternate_bouncer_scrim)
- as ScrimView
scrim.viewAlpha = 0f
bind(alternateBouncerView!!, alternateBouncerDependencies.get())
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/DeviceEntryIconViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/DeviceEntryIconViewBinder.kt
index cccb93c..4f00495 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/DeviceEntryIconViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/DeviceEntryIconViewBinder.kt
@@ -25,6 +25,7 @@
import androidx.core.view.isInvisible
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
+import com.android.app.tracing.coroutines.launch
import com.android.systemui.common.ui.view.LongPressHandlingView
import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor
import com.android.systemui.keyguard.ui.view.DeviceEntryIconView
@@ -33,6 +34,7 @@
import com.android.systemui.keyguard.ui.viewmodel.DeviceEntryIconViewModel
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.plugins.FalsingManager
+import com.android.systemui.res.R
import com.android.systemui.statusbar.VibratorHelper
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -40,6 +42,7 @@
@ExperimentalCoroutinesApi
object DeviceEntryIconViewBinder {
+ private const val TAG = "DeviceEntryIconViewBinder"
/**
* Updates UI for:
@@ -82,22 +85,40 @@
// GONE => AOD transition (even though the view may not be visible until the middle
// of the transition.
repeatOnLifecycle(Lifecycle.State.CREATED) {
- launch {
+ launch("$TAG#viewModel.isVisible") {
viewModel.isVisible.collect { isVisible ->
longPressHandlingView.isInvisible = !isVisible
}
}
- launch {
+ launch("$TAG#viewModel.isLongPressEnabled") {
viewModel.isLongPressEnabled.collect { isEnabled ->
longPressHandlingView.setLongPressHandlingEnabled(isEnabled)
}
}
- launch {
+ launch("$TAG#viewModel.isUdfpsSupported") {
+ viewModel.isUdfpsSupported.collect { udfpsSupported ->
+ longPressHandlingView.longPressDuration =
+ if (udfpsSupported) {
+ {
+ view.resources
+ .getInteger(R.integer.config_udfpsDeviceEntryIconLongPress)
+ .toLong()
+ }
+ } else {
+ {
+ view.resources
+ .getInteger(R.integer.config_lockIconLongPress)
+ .toLong()
+ }
+ }
+ }
+ }
+ launch("$TAG#viewModel.accessibilityDelegateHint") {
viewModel.accessibilityDelegateHint.collect { hint ->
view.accessibilityHintType = hint
}
}
- launch {
+ launch("$TAG#viewModel.useBackgroundProtection") {
viewModel.useBackgroundProtection.collect { useBackgroundProtection ->
if (useBackgroundProtection) {
bgView.visibility = View.VISIBLE
@@ -106,7 +127,7 @@
}
}
}
- launch {
+ launch("$TAG#viewModel.burnInOffsets") {
viewModel.burnInOffsets.collect { burnInOffsets ->
view.translationX = burnInOffsets.x.toFloat()
view.translationY = burnInOffsets.y.toFloat()
@@ -114,7 +135,9 @@
}
}
- launch { viewModel.deviceEntryViewAlpha.collect { alpha -> view.alpha = alpha } }
+ launch("$TAG#viewModel.deviceEntryViewAlpha") {
+ viewModel.deviceEntryViewAlpha.collect { alpha -> view.alpha = alpha }
+ }
}
}
@@ -122,14 +145,18 @@
repeatOnLifecycle(Lifecycle.State.STARTED) {
// Start with an empty state
fgIconView.setImageState(StateSet.NOTHING, /* merge */ false)
- launch {
+ launch("$TAG#fpIconView.viewModel") {
fgViewModel.viewModel.collect { viewModel ->
fgIconView.setImageState(
view.getIconState(viewModel.type, viewModel.useAodVariant),
/* merge */ false
)
- fgIconView.contentDescription =
- fgIconView.resources.getString(viewModel.type.contentDescriptionResId)
+ if (viewModel.type.contentDescriptionResId != -1) {
+ fgIconView.contentDescription =
+ fgIconView.resources.getString(
+ viewModel.type.contentDescriptionResId
+ )
+ }
fgIconView.imageTintList = ColorStateList.valueOf(viewModel.tint)
fgIconView.setPadding(
viewModel.padding,
@@ -144,8 +171,10 @@
bgView.repeatWhenAttached {
repeatOnLifecycle(Lifecycle.State.CREATED) {
- launch { bgViewModel.alpha.collect { alpha -> bgView.alpha = alpha } }
- launch {
+ launch("$TAG#bgViewModel.alpha") {
+ bgViewModel.alpha.collect { alpha -> bgView.alpha = alpha }
+ }
+ launch("$TAG#bgViewModel.color") {
bgViewModel.color.collect { color ->
bgView.imageTintList = ColorStateList.valueOf(color)
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt
index abd79ab..b9a79dc 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt
@@ -118,6 +118,7 @@
}
override fun destroy() {
+ view.setOnApplyWindowInsetsListener(null)
disposableHandle.dispose()
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/DeviceEntryIconTransitionModule.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/DeviceEntryIconTransitionModule.kt
index a8e9041..0f63f65 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/DeviceEntryIconTransitionModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/DeviceEntryIconTransitionModule.kt
@@ -41,6 +41,7 @@
import com.android.systemui.keyguard.ui.viewmodel.LockscreenToPrimaryBouncerTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.OccludedToAodTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.OccludedToLockscreenTransitionViewModel
+import com.android.systemui.keyguard.ui.viewmodel.OffToLockscreenTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToAodTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToDozingTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToLockscreenTransitionViewModel
@@ -196,6 +197,12 @@
@Binds
@IntoSet
+ abstract fun offToLockscreen(
+ impl: OffToLockscreenTransitionViewModel
+ ): DeviceEntryIconTransition
+
+ @Binds
+ @IntoSet
abstract fun primaryBouncerToAod(
impl: PrimaryBouncerToAodTransitionViewModel
): DeviceEntryIconTransition
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/DeviceEntryIconView.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/DeviceEntryIconView.kt
index 2735aed..35b2598 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/DeviceEntryIconView.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/DeviceEntryIconView.kt
@@ -40,10 +40,7 @@
attrs: AttributeSet?,
defStyleAttrs: Int = 0,
) : FrameLayout(context, attrs, defStyleAttrs) {
- val longPressHandlingView: LongPressHandlingView =
- LongPressHandlingView(context, attrs) {
- context.resources.getInteger(R.integer.config_lockIconLongPress).toLong()
- }
+ val longPressHandlingView: LongPressHandlingView = LongPressHandlingView(context, attrs)
val iconView: ImageView = ImageView(context, attrs).apply { id = R.id.device_entry_icon_fg }
val bgView: ImageView = ImageView(context, attrs).apply { id = R.id.device_entry_icon_bg }
val aodFpDrawable: LottieDrawable = LottieDrawable()
@@ -214,7 +211,7 @@
R.id.unlocked,
R.id.locked_aod,
context.getDrawable(R.drawable.unlocked_to_aod_lock) as AnimatedVectorDrawable,
- /* reversible */ true,
+ /* reversible */ false,
)
}
@@ -252,6 +249,7 @@
IconType.LOCK -> lockIconState[0] = android.R.attr.state_first
IconType.UNLOCK -> lockIconState[0] = android.R.attr.state_last
IconType.FINGERPRINT -> lockIconState[0] = android.R.attr.state_middle
+ IconType.NONE -> return StateSet.NOTHING
}
if (aod) {
lockIconState[1] = android.R.attr.state_single
@@ -265,6 +263,7 @@
LOCK(R.string.accessibility_lock_icon),
UNLOCK(R.string.accessibility_unlock_button),
FINGERPRINT(R.string.accessibility_fingerprint_label),
+ NONE(-1),
}
enum class AccessibilityHintType {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultShortcutsSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultShortcutsSection.kt
index 45b8257..9146c60 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultShortcutsSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultShortcutsSection.kt
@@ -18,6 +18,7 @@
package com.android.systemui.keyguard.ui.view.layout.sections
import android.content.res.Resources
+import android.view.WindowInsets
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
import androidx.constraintlayout.widget.ConstraintSet.BOTTOM
@@ -25,15 +26,19 @@
import androidx.constraintlayout.widget.ConstraintSet.PARENT_ID
import androidx.constraintlayout.widget.ConstraintSet.RIGHT
import androidx.constraintlayout.widget.ConstraintSet.VISIBILITY_MODE_IGNORE
+import com.android.systemui.animation.view.LaunchableImageView
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.keyguard.KeyguardBottomAreaRefactor
+import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor
import com.android.systemui.keyguard.ui.binder.KeyguardQuickAffordanceViewBinder
+import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.IntraBlueprintTransition
import com.android.systemui.keyguard.ui.viewmodel.KeyguardQuickAffordancesCombinedViewModel
import com.android.systemui.keyguard.ui.viewmodel.KeyguardRootViewModel
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.res.R
import com.android.systemui.statusbar.KeyguardIndicationController
import com.android.systemui.statusbar.VibratorHelper
+import dagger.Lazy
import javax.inject.Inject
class DefaultShortcutsSection
@@ -46,11 +51,29 @@
private val falsingManager: FalsingManager,
private val indicationController: KeyguardIndicationController,
private val vibratorHelper: VibratorHelper,
+ private val keyguardBlueprintInteractor: Lazy<KeyguardBlueprintInteractor>,
) : BaseShortcutSection() {
+
+ // Amount to increase the bottom margin by to avoid colliding with inset
+ private var safeInsetBottom = 0
+
override fun addViews(constraintLayout: ConstraintLayout) {
if (KeyguardBottomAreaRefactor.isEnabled) {
addLeftShortcut(constraintLayout)
addRightShortcut(constraintLayout)
+
+ constraintLayout
+ .requireViewById<LaunchableImageView>(R.id.start_button)
+ .setOnApplyWindowInsetsListener { _, windowInsets ->
+ val tempSafeInset = windowInsets?.displayCutout?.safeInsetBottom ?: 0
+ if (safeInsetBottom != tempSafeInset) {
+ safeInsetBottom = tempSafeInset
+ keyguardBlueprintInteractor
+ .get()
+ .refreshBlueprint(IntraBlueprintTransition.Type.DefaultTransition)
+ }
+ WindowInsets.CONSUMED
+ }
}
}
@@ -91,12 +114,24 @@
constrainWidth(R.id.start_button, width)
constrainHeight(R.id.start_button, height)
connect(R.id.start_button, LEFT, PARENT_ID, LEFT, horizontalOffsetMargin)
- connect(R.id.start_button, BOTTOM, PARENT_ID, BOTTOM, verticalOffsetMargin)
+ connect(
+ R.id.start_button,
+ BOTTOM,
+ PARENT_ID,
+ BOTTOM,
+ verticalOffsetMargin + safeInsetBottom
+ )
constrainWidth(R.id.end_button, width)
constrainHeight(R.id.end_button, height)
connect(R.id.end_button, RIGHT, PARENT_ID, RIGHT, horizontalOffsetMargin)
- connect(R.id.end_button, BOTTOM, PARENT_ID, BOTTOM, verticalOffsetMargin)
+ connect(
+ R.id.end_button,
+ BOTTOM,
+ PARENT_ID,
+ BOTTOM,
+ verticalOffsetMargin + safeInsetBottom
+ )
// The constraint set visibility for start and end button are default visible, set to
// ignore so the view's own initial visibility (invisible) is used
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SmartspaceSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SmartspaceSection.kt
index 9ec7a65..487c2e9 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SmartspaceSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SmartspaceSection.kt
@@ -42,10 +42,10 @@
val context: Context,
val keyguardClockViewModel: KeyguardClockViewModel,
val keyguardSmartspaceViewModel: KeyguardSmartspaceViewModel,
- val keyguardSmartspaceInteractor: KeyguardSmartspaceInteractor,
+ private val keyguardSmartspaceInteractor: KeyguardSmartspaceInteractor,
val smartspaceController: LockscreenSmartspaceController,
val keyguardUnlockAnimationController: KeyguardUnlockAnimationController,
- val blueprintInteractor: Lazy<KeyguardBlueprintInteractor>,
+ private val blueprintInteractor: Lazy<KeyguardBlueprintInteractor>,
) : KeyguardSection() {
private var smartspaceView: View? = null
private var weatherView: View? = null
@@ -61,12 +61,10 @@
weatherView = smartspaceController.buildAndConnectWeatherView(constraintLayout)
dateView = smartspaceController.buildAndConnectDateView(constraintLayout)
pastVisibility = smartspaceView?.visibility ?: View.GONE
- if (keyguardSmartspaceViewModel.isSmartspaceEnabled) {
- constraintLayout.addView(smartspaceView)
- if (keyguardSmartspaceViewModel.isDateWeatherDecoupled) {
- constraintLayout.addView(weatherView)
- constraintLayout.addView(dateView)
- }
+ constraintLayout.addView(smartspaceView)
+ if (keyguardSmartspaceViewModel.isDateWeatherDecoupled) {
+ constraintLayout.addView(weatherView)
+ constraintLayout.addView(dateView)
}
keyguardUnlockAnimationController.lockscreenSmartspace = smartspaceView
smartspaceVisibilityListener = OnGlobalLayoutListener {
@@ -205,13 +203,9 @@
constraintSet.apply {
val weatherVisibility =
- when (keyguardClockViewModel.hasCustomWeatherDataDisplay.value) {
- true -> ConstraintSet.GONE
- false ->
- when (keyguardSmartspaceViewModel.isWeatherEnabled) {
- true -> ConstraintSet.VISIBLE
- false -> ConstraintSet.GONE
- }
+ when (keyguardSmartspaceViewModel.isWeatherVisible.value) {
+ true -> ConstraintSet.VISIBLE
+ false -> ConstraintSet.GONE
}
setVisibility(sharedR.id.weather_smartspace_view, weatherVisibility)
setAlpha(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/transitions/ClockSizeTransition.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/transitions/ClockSizeTransition.kt
index 7c29b39..218967c 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/transitions/ClockSizeTransition.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/transitions/ClockSizeTransition.kt
@@ -38,6 +38,8 @@
import com.google.android.material.math.MathUtils
import kotlin.math.abs
+internal fun View.getRect(): Rect = Rect(this.left, this.top, this.right, this.bottom)
+
internal fun View.setRect(rect: Rect) =
this.setLeftTopRightBottom(rect.left, rect.top, rect.right, rect.bottom)
@@ -66,12 +68,18 @@
val view = transition.view
transition.values[PROP_VISIBILITY] = view.visibility
transition.values[PROP_ALPHA] = view.alpha
- transition.values[PROP_BOUNDS] = Rect(view.left, view.top, view.right, view.bottom)
+ transition.values[PROP_BOUNDS] = view.getRect()
if (!captureSmartspace) return
- val ss = (view.parent as View).findViewById<View>(sharedR.id.bc_smartspace_view)
- if (ss == null) return
- transition.values[SMARTSPACE_BOUNDS] = Rect(ss.left, ss.top, ss.right, ss.bottom)
+ val parent = view.parent as View
+ val targetSSView =
+ parent.findViewById<View>(sharedR.id.bc_smartspace_view)
+ ?: parent.findViewById<View>(R.id.keyguard_slice_view)
+ if (targetSSView == null) {
+ Log.e(TAG, "Failed to find smartspace equivalent target for animation")
+ return
+ }
+ transition.values[SMARTSPACE_BOUNDS] = targetSSView.getRect()
}
open fun mutateBounds(
@@ -89,7 +97,13 @@
startValues: TransitionValues?,
endValues: TransitionValues?
): Animator? {
- if (startValues == null || endValues == null) return null
+ if (startValues == null || endValues == null) {
+ Log.w(
+ TAG,
+ "Couldn't create animator: startValues=$startValues; endValues=$endValues"
+ )
+ return null
+ }
var fromVis = startValues.values[PROP_VISIBILITY] as Int
var fromIsVis = fromVis == View.VISIBLE
@@ -141,11 +155,12 @@
fun assignAnimValues(src: String, fract: Float, vis: Int? = null) {
val bounds = computeBounds(fract)
val alpha = MathUtils.lerp(fromAlpha, toAlpha, fract)
- if (DEBUG)
+ if (DEBUG) {
Log.i(
TAG,
"$src: $toView; fract=$fract; alpha=$alpha; vis=$vis; bounds=$bounds;"
)
+ }
toView.setVisibility(vis ?: View.VISIBLE)
toView.setAlpha(alpha)
toView.setRect(bounds)
@@ -245,12 +260,9 @@
// Move normally if clock is not changing visibility
if (fromIsVis == toIsVis) return
- fromBounds.left = toBounds.left
- fromBounds.right = toBounds.right
+ fromBounds.set(toBounds)
if (viewModel.isLargeClockVisible.value) {
- // Large clock shouldn't move
- fromBounds.top = toBounds.top
- fromBounds.bottom = toBounds.bottom
+ // Large clock shouldn't move; fromBounds already set
} else if (toSSBounds != null && fromSSBounds != null) {
// Instead of moving the small clock the full distance, we compute the distance
// smartspace will move. We then scale this to match the duration of this animation
@@ -306,12 +318,9 @@
// Move normally if clock is not changing visibility
if (fromIsVis == toIsVis) return
- toBounds.left = fromBounds.left
- toBounds.right = fromBounds.right
+ toBounds.set(fromBounds)
if (!viewModel.isLargeClockVisible.value) {
- // Large clock shouldn't move
- toBounds.top = fromBounds.top
- toBounds.bottom = fromBounds.bottom
+ // Large clock shouldn't move; toBounds already set
} else if (toSSBounds != null && fromSSBounds != null) {
// Instead of moving the small clock the full distance, we compute the distance
// smartspace will move. We then scale this to match the duration of this animation
@@ -321,7 +330,7 @@
toBounds.top = fromBounds.top - ssTranslation
toBounds.bottom = fromBounds.bottom - ssTranslation
} else {
- Log.w(TAG, "mutateBounds: smallClock received no smartspace bounds")
+ Log.e(TAG, "mutateBounds: smallClock received no smartspace bounds")
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlows.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlows.kt
index e0a3af6..570f377 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlows.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlows.kt
@@ -102,37 +102,40 @@
to = GONE,
)
- return shadeInteractor.isAnyExpanded.flatMapLatest { isAnyExpanded ->
- transitionAnimation
- .sharedFlow(
- duration = duration,
- interpolator = EMPHASIZED_ACCELERATE,
- onStart = {
- leaveShadeOpen = statusBarStateController.leaveOpenOnKeyguardHide()
- willRunDismissFromKeyguard = willRunAnimationOnKeyguard()
- isShadeExpanded = isAnyExpanded
- },
- onStep = { 1f - it },
- )
- .map {
- if (willRunDismissFromKeyguard) {
- if (isShadeExpanded) {
+ return shadeInteractor.anyExpansion
+ .map { it > 0f }
+ .distinctUntilChanged()
+ .flatMapLatest { isAnyExpanded ->
+ transitionAnimation
+ .sharedFlow(
+ duration = duration,
+ interpolator = EMPHASIZED_ACCELERATE,
+ onStart = {
+ leaveShadeOpen = statusBarStateController.leaveOpenOnKeyguardHide()
+ willRunDismissFromKeyguard = willRunAnimationOnKeyguard()
+ isShadeExpanded = isAnyExpanded
+ },
+ onStep = { 1f - it },
+ )
+ .map {
+ if (willRunDismissFromKeyguard) {
+ if (isShadeExpanded) {
+ ScrimAlpha(
+ behindAlpha = it,
+ notificationsAlpha = it,
+ )
+ } else {
+ ScrimAlpha()
+ }
+ } else if (leaveShadeOpen) {
ScrimAlpha(
- behindAlpha = it,
- notificationsAlpha = it,
+ behindAlpha = 1f,
+ notificationsAlpha = 1f,
)
} else {
- ScrimAlpha()
+ ScrimAlpha(behindAlpha = it)
}
- } else if (leaveShadeOpen) {
- ScrimAlpha(
- behindAlpha = 1f,
- notificationsAlpha = 1f,
- )
- } else {
- ScrimAlpha(behindAlpha = it)
}
- }
- }
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModel.kt
index 45dca99..da2fcc4 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModel.kt
@@ -50,6 +50,7 @@
import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.shareIn
+import kotlinx.coroutines.flow.stateIn
/** Models the UI state for the containing device entry icon & long-press handling view. */
@ExperimentalCoroutinesApi
@@ -83,19 +84,21 @@
.map { it.deviceEntryParentViewAlpha }
.merge()
.shareIn(scope, SharingStarted.WhileSubscribed())
+ .onStart { emit(initialAlphaFromKeyguardState(transitionInteractor.getCurrentState())) }
private val alphaMultiplierFromShadeExpansion: Flow<Float> =
combine(
- showingAlternateBouncer,
- shadeExpansion,
- qsProgress,
- ) { showingAltBouncer, shadeExpansion, qsProgress ->
- val interpolatedQsProgress = (qsProgress * 2).coerceIn(0f, 1f)
- if (showingAltBouncer) {
- 1f
- } else {
- (1f - shadeExpansion) * (1f - interpolatedQsProgress)
+ showingAlternateBouncer,
+ shadeExpansion,
+ qsProgress,
+ ) { showingAltBouncer, shadeExpansion, qsProgress ->
+ val interpolatedQsProgress = (qsProgress * 2).coerceIn(0f, 1f)
+ if (showingAltBouncer) {
+ 1f
+ } else {
+ (1f - shadeExpansion) * (1f - interpolatedQsProgress)
+ }
}
- }
+ .onStart { emit(1f) }
// Burn-in offsets in AOD
private val nonAnimatedBurnInOffsets: Flow<BurnInOffsets> =
combine(
@@ -110,27 +113,7 @@
)
}
- private val dozeAmount: Flow<Float> =
- combine(
- transitionInteractor.startedKeyguardTransitionStep,
- merge(
- transitionInteractor.transitionStepsFromState(KeyguardState.AOD).map {
- 1f - it.value
- },
- transitionInteractor.transitionStepsToState(KeyguardState.AOD).map { it.value }
- ),
- ) { startedKeyguardTransitionStep, aodTransitionAmount ->
- if (
- startedKeyguardTransitionStep.to == KeyguardState.AOD ||
- startedKeyguardTransitionStep.from == KeyguardState.AOD
- ) {
- aodTransitionAmount
- } else {
- // in case a new transition (ie: to occluded) cancels a transition to or from
- // aod, then we want to make sure the doze amount is still updated to 0
- 0f
- }
- }
+ private val dozeAmount: Flow<Float> = transitionInteractor.transitionValue(KeyguardState.AOD)
// Burn-in offsets that animate based on the transition amount to AOD
private val animatedBurnInOffsets: Flow<BurnInOffsets> =
combine(nonAnimatedBurnInOffsets, dozeAmount) { burnInOffsets, dozeAmount ->
@@ -143,52 +126,75 @@
val deviceEntryViewAlpha: Flow<Float> =
combine(
- transitionAlpha,
- alphaMultiplierFromShadeExpansion,
- ) { alpha, alphaMultiplier ->
- alpha * alphaMultiplier
+ transitionAlpha,
+ alphaMultiplierFromShadeExpansion,
+ ) { alpha, alphaMultiplier ->
+ alpha * alphaMultiplier
+ }
+ .stateIn(
+ scope = scope,
+ started = SharingStarted.WhileSubscribed(),
+ initialValue = 0f,
+ )
+
+ private fun initialAlphaFromKeyguardState(keyguardState: KeyguardState): Float {
+ return when (keyguardState) {
+ KeyguardState.OFF,
+ KeyguardState.PRIMARY_BOUNCER,
+ KeyguardState.DOZING,
+ KeyguardState.DREAMING,
+ KeyguardState.GLANCEABLE_HUB,
+ KeyguardState.GONE,
+ KeyguardState.OCCLUDED,
+ KeyguardState.DREAMING_LOCKSCREEN_HOSTED, -> 0f
+ KeyguardState.AOD,
+ KeyguardState.ALTERNATE_BOUNCER,
+ KeyguardState.LOCKSCREEN -> 1f
}
+ }
val useBackgroundProtection: StateFlow<Boolean> = isUdfpsSupported
val burnInOffsets: Flow<BurnInOffsets> =
- deviceEntryUdfpsInteractor.isUdfpsEnrolledAndEnabled.flatMapLatest { udfpsEnrolled ->
- if (udfpsEnrolled) {
- combine(
- transitionInteractor.startedKeyguardTransitionStep.sample(
- shadeInteractor.isAnyFullyExpanded,
- ::Pair
- ),
- animatedBurnInOffsets,
- nonAnimatedBurnInOffsets,
- ) {
- (startedTransitionStep, shadeExpanded),
- animatedBurnInOffsets,
- nonAnimatedBurnInOffsets ->
- if (startedTransitionStep.to == KeyguardState.AOD) {
- when (startedTransitionStep.from) {
- KeyguardState.ALTERNATE_BOUNCER -> animatedBurnInOffsets
- KeyguardState.LOCKSCREEN ->
- if (shadeExpanded) {
- nonAnimatedBurnInOffsets
- } else {
- animatedBurnInOffsets
- }
- else -> nonAnimatedBurnInOffsets
+ deviceEntryUdfpsInteractor.isUdfpsEnrolledAndEnabled
+ .flatMapLatest { udfpsEnrolled ->
+ if (udfpsEnrolled) {
+ combine(
+ transitionInteractor.startedKeyguardTransitionStep.sample(
+ shadeInteractor.isAnyFullyExpanded,
+ ::Pair
+ ),
+ animatedBurnInOffsets,
+ nonAnimatedBurnInOffsets,
+ ) {
+ (startedTransitionStep, shadeExpanded),
+ animatedBurnInOffsets,
+ nonAnimatedBurnInOffsets ->
+ if (startedTransitionStep.to == KeyguardState.AOD) {
+ when (startedTransitionStep.from) {
+ KeyguardState.ALTERNATE_BOUNCER -> animatedBurnInOffsets
+ KeyguardState.LOCKSCREEN ->
+ if (shadeExpanded) {
+ nonAnimatedBurnInOffsets
+ } else {
+ animatedBurnInOffsets
+ }
+ else -> nonAnimatedBurnInOffsets
+ }
+ } else if (startedTransitionStep.from == KeyguardState.AOD) {
+ when (startedTransitionStep.to) {
+ KeyguardState.LOCKSCREEN -> animatedBurnInOffsets
+ else -> BurnInOffsets(x = 0, y = 0, progress = 0f)
+ }
+ } else {
+ BurnInOffsets(x = 0, y = 0, progress = 0f)
}
- } else if (startedTransitionStep.from == KeyguardState.AOD) {
- when (startedTransitionStep.to) {
- KeyguardState.LOCKSCREEN -> animatedBurnInOffsets
- else -> BurnInOffsets(x = 0, y = 0, progress = 0f)
- }
- } else {
- BurnInOffsets(x = 0, y = 0, progress = 0f)
}
+ } else {
+ // If UDFPS isn't enrolled, we don't show any UI on AOD so there's no need
+ // to use burn in offsets at all
+ flowOf(BurnInOffsets(x = 0, y = 0, progress = 0f))
}
- } else {
- // If UDFPS isn't enrolled, we don't show any UI on AOD so there's no need
- // to use burn in offsets at all
- flowOf(BurnInOffsets(x = 0, y = 0, progress = 0f))
}
- }
+ .distinctUntilChanged()
private val isUnlocked: Flow<Boolean> =
keyguardInteractor.isKeyguardDismissible.flatMapLatest { isUnlocked ->
@@ -211,7 +217,14 @@
isUnlocked,
) { isListeningForUdfps, isUnlocked ->
if (isListeningForUdfps) {
- DeviceEntryIconView.IconType.FINGERPRINT
+ if (isUnlocked) {
+ // Don't show any UI until isUnlocked=false. This covers the case
+ // when the "Power button instantly locks > 0s" or the device doesn't lock
+ // immediately after a screen time.
+ DeviceEntryIconView.IconType.NONE
+ } else {
+ DeviceEntryIconView.IconType.FINGERPRINT
+ }
} else if (isUnlocked) {
DeviceEntryIconView.IconType.UNLOCK
} else {
@@ -227,7 +240,8 @@
when (deviceEntryStatus) {
DeviceEntryIconView.IconType.LOCK -> isUdfps
DeviceEntryIconView.IconType.UNLOCK -> true
- DeviceEntryIconView.IconType.FINGERPRINT -> false
+ DeviceEntryIconView.IconType.FINGERPRINT,
+ DeviceEntryIconView.IconType.NONE -> false
}
}
@@ -255,8 +269,8 @@
DeviceEntryIconView.IconType.LOCK ->
DeviceEntryIconView.AccessibilityHintType.AUTHENTICATE
DeviceEntryIconView.IconType.UNLOCK -> DeviceEntryIconView.AccessibilityHintType.ENTER
- DeviceEntryIconView.IconType.FINGERPRINT ->
- DeviceEntryIconView.AccessibilityHintType.NONE
+ DeviceEntryIconView.IconType.FINGERPRINT,
+ DeviceEntryIconView.IconType.NONE -> DeviceEntryIconView.AccessibilityHintType.NONE
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModel.kt
index 1f544c1..198e9f2 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModel.kt
@@ -84,8 +84,8 @@
combine(
isLargeClockVisible,
currentClock,
- ) { isLargeClock, clock ->
- clock?.let { clock ->
+ ) { isLargeClock, currentClock ->
+ currentClock?.let { clock ->
val face = if (isLargeClock) clock.largeClock else clock.smallClock
face.config.hasCustomWeatherDataDisplay
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt
index 24a7c51..bbcea56 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt
@@ -42,7 +42,7 @@
import com.android.systemui.statusbar.notification.domain.interactor.NotificationsKeyguardInteractor
import com.android.systemui.statusbar.phone.DozeParameters
import com.android.systemui.statusbar.phone.ScreenOffAnimationController
-import com.android.systemui.util.kotlin.BooleanFlowOperators.or
+import com.android.systemui.util.kotlin.BooleanFlowOperators.anyOf
import com.android.systemui.util.kotlin.pairwise
import com.android.systemui.util.kotlin.sample
import com.android.systemui.util.ui.AnimatableEvent
@@ -64,7 +64,6 @@
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.onStart
-import kotlinx.coroutines.launch
@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
@@ -134,7 +133,7 @@
private val isOnLockscreen: Flow<Boolean> =
combine(
keyguardTransitionInteractor.isFinishedInState(LOCKSCREEN).onStart { emit(false) },
- or(
+ anyOf(
keyguardTransitionInteractor.isInTransitionToState(LOCKSCREEN),
keyguardTransitionInteractor.isInTransitionFromState(LOCKSCREEN),
),
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardSmartspaceViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardSmartspaceViewModel.kt
index dc053aa..c0b1f95 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardSmartspaceViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardSmartspaceViewModel.kt
@@ -26,6 +26,7 @@
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
@@ -41,8 +42,8 @@
/** Whether the smartspace section is available in the build. */
val isSmartspaceEnabled: Boolean = smartspaceController.isEnabled()
/** Whether the weather area is available in the build. */
- // TODO(b/317891876): this should be a Flow as the value can change over time.
- val isWeatherEnabled: Boolean = smartspaceController.isWeatherEnabled()
+ private val isWeatherEnabled: StateFlow<Boolean> = smartspaceInteractor.isWeatherEnabled
+
/** Whether the data and weather areas are decoupled in the build. */
val isDateWeatherDecoupled: Boolean = smartspaceController.isDateWeatherDecoupled()
@@ -58,8 +59,10 @@
/** Whether the weather area should be visible. */
val isWeatherVisible: StateFlow<Boolean> =
- keyguardClockViewModel.hasCustomWeatherDataDisplay
- .map { clockIncludesCustomWeatherDisplay ->
+ combine(
+ isWeatherEnabled,
+ keyguardClockViewModel.hasCustomWeatherDataDisplay,
+ ) { isWeatherEnabled, clockIncludesCustomWeatherDisplay ->
isWeatherVisible(
clockIncludesCustomWeatherDisplay = clockIncludesCustomWeatherDisplay,
isWeatherEnabled = isWeatherEnabled,
@@ -72,7 +75,7 @@
isWeatherVisible(
clockIncludesCustomWeatherDisplay =
keyguardClockViewModel.hasCustomWeatherDataDisplay.value,
- isWeatherEnabled = isWeatherEnabled,
+ isWeatherEnabled = smartspaceInteractor.isWeatherEnabled.value,
)
)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModel.kt
index d4c8456e..d8b5013 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModel.kt
@@ -88,12 +88,11 @@
isCommunalAvailable: Boolean,
shadeMode: ShadeMode,
): Map<UserAction, UserActionResult> {
+ val shadeSceneKey =
+ if (shadeMode is ShadeMode.Dual) Scenes.NotificationsShade else Scenes.Shade
+
val quickSettingsIfSingleShade =
- if (shadeMode is ShadeMode.Single) {
- Scenes.QuickSettings
- } else {
- Scenes.Shade
- }
+ if (shadeMode is ShadeMode.Single) Scenes.QuickSettings else shadeSceneKey
return mapOf(
Swipe.Left to UserActionResult(Scenes.Communal).takeIf { isCommunalAvailable },
@@ -101,11 +100,17 @@
// Swiping down from the top edge goes to QS (or shade if in split shade mode).
swipeDownFromTop(pointerCount = 1) to quickSettingsIfSingleShade,
- swipeDownFromTop(pointerCount = 2) to quickSettingsIfSingleShade,
+ swipeDownFromTop(pointerCount = 2) to
+ // TODO(b/338577208): Remove 'Dual' once we add Dual Shade invocation zones.
+ if (shadeMode is ShadeMode.Dual) {
+ Scenes.QuickSettingsShade
+ } else {
+ quickSettingsIfSingleShade
+ },
// Swiping down, not from the edge, always navigates to the shade scene.
- swipeDown(pointerCount = 1) to Scenes.Shade,
- swipeDown(pointerCount = 2) to Scenes.Shade,
+ swipeDown(pointerCount = 1) to shadeSceneKey,
+ swipeDown(pointerCount = 2) to shadeSceneKey,
)
.filterValues { it != null }
.mapValues { checkNotNull(it.value) }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OffToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OffToLockscreenTransitionViewModel.kt
index 74094be..cf6a533 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OffToLockscreenTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OffToLockscreenTransitionViewModel.kt
@@ -19,6 +19,7 @@
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
+import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
import javax.inject.Inject
import kotlin.time.Duration.Companion.milliseconds
import kotlinx.coroutines.flow.Flow
@@ -28,7 +29,7 @@
@Inject
constructor(
animationFlow: KeyguardTransitionAnimationFlow,
-) {
+) : DeviceEntryIconTransition {
private val transitionAnimation =
animationFlow.setup(
@@ -43,4 +44,7 @@
onStep = { it },
onCancel = { 0f },
)
+
+ override val deviceEntryParentViewAlpha: Flow<Float> =
+ transitionAnimation.immediatelyTransitionTo(1f)
}
diff --git a/packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt b/packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt
index c997617..bf80e18 100644
--- a/packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt
+++ b/packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt
@@ -70,8 +70,7 @@
// dispatcher to use. We don't want it to run on the Dispatchers.Default thread pool as
// default behavior. Instead, we want it to run on the view's UI thread since the user will
// presumably want to call view methods that require being called from said UI thread.
- val lifecycleCoroutineContext =
- Dispatchers.Main + createCoroutineTracingContext() + coroutineContext
+ val lifecycleCoroutineContext = MAIN_DISPATCHER_SINGLETON + coroutineContext
val traceName =
if (Compile.IS_DEBUG && coroutineTracing()) {
inferTraceSectionName()
@@ -205,17 +204,28 @@
StackWalker.getInstance().walk { stream ->
stream.filter(::isFrameInteresting).limit(5).findFirst()
}
- if (interestingFrame.isPresent) {
+ return if (interestingFrame.isPresent) {
val f = interestingFrame.get()
- return "${f.className}#${f.methodName}:${f.lineNumber} [$DEFAULT_TRACE_NAME]"
+ "${f.className}#${f.methodName}:${f.lineNumber} [$DEFAULT_TRACE_NAME]"
} else {
- return DEFAULT_TRACE_NAME
+ DEFAULT_TRACE_NAME
}
} finally {
Trace.traceEnd(Trace.TRACE_TAG_APP)
}
}
+/**
+ * Even though there is only has one usage of `Dispatchers.Main` in this file, we cache it in a
+ * top-level property so that we do not unnecessarily create new `CoroutineContext` objects for
+ * tracing on each call to [repeatWhenAttached]. It is okay to reuse a single instance of the
+ * tracing context because it is copied for its children.
+ *
+ * Also, ideally, we would use the injected `@Main CoroutineDispatcher`, but [repeatWhenAttached] is
+ * an extension function, and plumbing dagger-injected instances for static usage has little
+ * benefit.
+ */
+private val MAIN_DISPATCHER_SINGLETON = Dispatchers.Main + createCoroutineTracingContext()
private const val DEFAULT_TRACE_NAME = "repeatWhenAttached"
private const val CURRENT_CLASS_NAME = "com.android.systemui.lifecycle.RepeatWhenAttachedKt"
private const val JAVA_ADAPTER_CLASS_NAME = "com.android.systemui.util.kotlin.JavaAdapterKt"
diff --git a/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt b/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt
index 9e6c552..b276f53 100644
--- a/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt
@@ -201,6 +201,10 @@
)
}
+ fun addLockoutResetCallbackDone() {
+ logBuffer.log(TAG, DEBUG, {}, { "addlockoutResetCallback done" })
+ }
+
fun authRequested(uiEvent: FaceAuthUiEvent) {
logBuffer.log(
TAG,
diff --git a/packages/SystemUI/src/com/android/systemui/model/SceneContainerPlugin.kt b/packages/SystemUI/src/com/android/systemui/model/SceneContainerPlugin.kt
index 1704812..89e4760 100644
--- a/packages/SystemUI/src/com/android/systemui/model/SceneContainerPlugin.kt
+++ b/packages/SystemUI/src/com/android/systemui/model/SceneContainerPlugin.kt
@@ -55,7 +55,7 @@
val transitionState = sceneInteractor.get().transitionState.value
val idleTransitionStateOrNull = transitionState as? ObservableTransitionState.Idle
- val currentSceneOrNull = idleTransitionStateOrNull?.scene
+ val currentSceneOrNull = idleTransitionStateOrNull?.currentScene
val invisibleDueToOcclusion = occlusionInteractor.get().invisibleDueToOcclusion.value
return currentSceneOrNull?.let { sceneKey ->
EvaluatorByFlag[flag]?.invoke(
@@ -81,8 +81,14 @@
val EvaluatorByFlag =
mapOf<Int, (SceneContainerPluginState) -> Boolean>(
SYSUI_STATE_NOTIFICATION_PANEL_VISIBLE to { it.scene != Scenes.Gone },
- SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED to { it.scene == Scenes.Shade },
- SYSUI_STATE_QUICK_SETTINGS_EXPANDED to { it.scene == Scenes.QuickSettings },
+ SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED to
+ {
+ it.scene == Scenes.NotificationsShade || it.scene == Scenes.Shade
+ },
+ SYSUI_STATE_QUICK_SETTINGS_EXPANDED to
+ {
+ it.scene == Scenes.QuickSettingsShade || it.scene == Scenes.QuickSettings
+ },
SYSUI_STATE_BOUNCER_SHOWING to { it.scene == Scenes.Bouncer },
SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING to
{
diff --git a/packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeSceneViewModel.kt b/packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeSceneViewModel.kt
new file mode 100644
index 0000000..f677ec1b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeSceneViewModel.kt
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.notifications.ui.viewmodel
+
+import com.android.compose.animation.scene.Back
+import com.android.compose.animation.scene.SceneKey
+import com.android.compose.animation.scene.Swipe
+import com.android.compose.animation.scene.UserAction
+import com.android.compose.animation.scene.UserActionResult
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.shade.ui.viewmodel.OverlayShadeViewModel
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.stateIn
+
+/** Models UI state and handles user input for the Notifications Shade scene. */
+@SysUISingleton
+class NotificationsShadeSceneViewModel
+@Inject
+constructor(
+ @Application private val applicationScope: CoroutineScope,
+ overlayShadeViewModel: OverlayShadeViewModel,
+) {
+ val destinationScenes: StateFlow<Map<UserAction, UserActionResult>> =
+ overlayShadeViewModel.backgroundScene
+ .map(::destinationScenes)
+ .stateIn(
+ scope = applicationScope,
+ started = SharingStarted.WhileSubscribed(),
+ initialValue = destinationScenes(overlayShadeViewModel.backgroundScene.value),
+ )
+
+ private fun destinationScenes(backgroundScene: SceneKey): Map<UserAction, UserActionResult> {
+ return mapOf(
+ Swipe.Up to backgroundScene,
+ Back to backgroundScene,
+ )
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
index d476e63..a14479b 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
@@ -67,6 +67,7 @@
import com.android.systemui.SystemUIApplication;
import com.android.systemui.animation.DialogCuj;
import com.android.systemui.animation.DialogTransitionAnimator;
+import com.android.systemui.animation.Expandable;
import com.android.systemui.broadcast.BroadcastSender;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.plugins.ActivityStarter;
@@ -323,7 +324,7 @@
// remaining estimate is disabled
if (!mCurrentBatterySnapshot.isHybrid() || mBucket < -1
|| mCurrentBatterySnapshot.getTimeRemainingMillis()
- < mCurrentBatterySnapshot.getSevereThresholdMillis()) {
+ < mCurrentBatterySnapshot.getSevereThresholdMillis()) {
nb.setColor(Utils.getColorAttrDefaultColor(mContext, android.R.attr.colorError));
}
@@ -703,17 +704,23 @@
mSaverConfirmation = null;
logEvent(BatteryWarningEvents.LowBatteryWarningEvent.SAVER_CONFIRM_DISMISS);
});
- WeakReference<View> ref = mBatteryControllerLazy.get().getLastPowerSaverStartView();
- if (ref != null && ref.get() != null && ref.get().isAggregatedVisible()) {
- mDialogTransitionAnimator.showFromView(d, ref.get(),
+ WeakReference<Expandable> ref =
+ mBatteryControllerLazy.get().getLastPowerSaverStartExpandable();
+ if (ref != null && ref.get() != null) {
+ DialogTransitionAnimator.Controller controller = ref.get().dialogTransitionController(
new DialogCuj(InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN,
INTERACTION_JANK_TAG));
+ if (controller != null) {
+ mDialogTransitionAnimator.show(d, controller);
+ } else {
+ d.show();
+ }
} else {
d.show();
}
logEvent(BatteryWarningEvents.LowBatteryWarningEvent.SAVER_CONFIRM_DIALOG);
mSaverConfirmation = d;
- mBatteryControllerLazy.get().clearLastPowerSaverStartView();
+ mBatteryControllerLazy.get().clearLastPowerSaverStartExpandable();
}
@VisibleForTesting
@@ -873,4 +880,4 @@
}
}
}
-}
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java
index b705a03..ea89be6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java
@@ -21,6 +21,7 @@
import android.content.Context;
import android.os.Handler;
+import com.android.systemui.bluetooth.qsdialog.BluetoothTileDialogModule;
import com.android.systemui.dagger.NightDisplayListenerModule;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Background;
@@ -60,6 +61,7 @@
*/
@Module(subcomponents = {QSFragmentComponent.class, QSSceneComponent.class},
includes = {
+ BluetoothTileDialogModule.class,
MediaModule.class,
PanelsModule.class,
QSExternalModule.class,
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
index b53c245..d26ae0a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
@@ -41,7 +41,6 @@
import android.text.format.DateUtils;
import android.util.Log;
import android.view.IWindowManager;
-import android.view.View;
import android.view.WindowManagerGlobal;
import android.widget.Switch;
@@ -52,6 +51,7 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.animation.ActivityTransitionAnimator;
+import com.android.systemui.animation.Expandable;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
@@ -99,7 +99,7 @@
@Nullable
private CharSequence mDefaultLabel;
@Nullable
- private View mViewClicked;
+ private Expandable mExpandableClicked;
private final Context mUserContext;
@@ -347,7 +347,7 @@
mService.onStartListening();
}
} else {
- mViewClicked = null;
+ mExpandableClicked = null;
mService.onStopListening();
if (mIsTokenGranted && !mIsShowingDialog) {
try {
@@ -409,11 +409,11 @@
}
@Override
- protected void handleClick(@Nullable View view) {
+ protected void handleClick(@Nullable Expandable expandable) {
if (mTile.getState() == Tile.STATE_UNAVAILABLE) {
return;
}
- mViewClicked = view;
+ mExpandableClicked = expandable;
try {
if (DEBUG) Log.d(TAG, "Adding token");
mWindowManager.addWindowToken(mToken, TYPE_QS_DIALOG,
@@ -541,11 +541,9 @@
Log.i(TAG, "The activity is starting");
ActivityTransitionAnimator.Controller controller =
- mViewClicked == null ? null :
- ActivityTransitionAnimator.Controller.fromView(
- mViewClicked,
- InteractionJankMonitor.CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE
- );
+ mExpandableClicked == null ? null :
+ mExpandableClicked.activityTransitionController(
+ InteractionJankMonitor.CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE);
mActivityStarter.startPendingIntentMaybeDismissingKeyguard(
pendingIntent,
/* intentSentUiThreadCallback= */ null,
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
index 880289e..2a726c2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
@@ -15,6 +15,8 @@
*/
package com.android.systemui.qs.external;
+import static android.os.PowerWhitelistManager.REASON_TILE_ONCLICK;
+import static android.provider.DeviceConfig.NAMESPACE_SYSTEMUI;
import static android.service.quicksettings.TileService.START_ACTIVITY_NEEDS_PENDING_INTENT;
import android.app.ActivityManager;
@@ -31,8 +33,10 @@
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
+import android.os.IDeviceIdleController;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.provider.DeviceConfig;
import android.service.quicksettings.IQSService;
import android.service.quicksettings.IQSTileService;
import android.service.quicksettings.TileService;
@@ -89,7 +93,9 @@
private static final int MAX_BIND_RETRIES = 5;
private static final long DEFAULT_BIND_RETRY_DELAY = 5 * DateUtils.SECOND_IN_MILLIS;
private static final long LOW_MEMORY_BIND_RETRY_DELAY = 20 * DateUtils.SECOND_IN_MILLIS;
-
+ private static final long TILE_SERVICE_ONCLICK_ALLOW_LIST_DEFAULT_DURATION_MS = 15_000;
+ private static final String PROPERTY_TILE_SERVICE_ONCLICK_ALLOW_LIST_DURATION =
+ "property_tile_service_onclick_allow_list_duration";
// Shared prefs that hold tile lifecycle info.
private static final String TILES = "tiles_prefs";
@@ -102,6 +108,7 @@
private final PackageManagerAdapter mPackageManagerAdapter;
private final BroadcastDispatcher mBroadcastDispatcher;
private final ActivityManager mActivityManager;
+ private final IDeviceIdleController mDeviceIdleController;
private Set<Integer> mQueuedMessages = new ArraySet<>();
@NonNull
@@ -120,12 +127,15 @@
private TileChangeListener mChangeListener;
// Return value from bindServiceAsUser, determines whether safe to call unbind.
private AtomicBoolean mIsBound = new AtomicBoolean(false);
+ private long mTempAllowFgsLaunchDuration = TILE_SERVICE_ONCLICK_ALLOW_LIST_DEFAULT_DURATION_MS;
+ private final DeviceConfig.OnPropertiesChangedListener mDeviceConfigChangedListener;
+ private AtomicBoolean mDeviceConfigChangedListenerRegistered = new AtomicBoolean(false);
@AssistedInject
TileLifecycleManager(@Main Handler handler, Context context, IQSService service,
PackageManagerAdapter packageManagerAdapter, BroadcastDispatcher broadcastDispatcher,
@Assisted Intent intent, @Assisted UserHandle user, ActivityManager activityManager,
- @Background DelayableExecutor executor) {
+ IDeviceIdleController deviceIdleController, @Background DelayableExecutor executor) {
mContext = context;
mHandler = handler;
mIntent = intent;
@@ -136,6 +146,16 @@
mPackageManagerAdapter = packageManagerAdapter;
mBroadcastDispatcher = broadcastDispatcher;
mActivityManager = activityManager;
+ mDeviceIdleController = deviceIdleController;
+ mDeviceConfigChangedListener = properties -> {
+ if (!DeviceConfig.NAMESPACE_SYSTEMUI.equals(properties.getNamespace())) {
+ return;
+ }
+ mTempAllowFgsLaunchDuration = properties.getLong(
+ PROPERTY_TILE_SERVICE_ONCLICK_ALLOW_LIST_DURATION,
+ TILE_SERVICE_ONCLICK_ALLOW_LIST_DEFAULT_DURATION_MS);
+ };
+
if (mDebug) Log.d(TAG, "Creating " + mIntent + " " + mUser);
}
@@ -211,6 +231,13 @@
}
mBound.set(bind);
if (bind) {
+ if (mDeviceConfigChangedListenerRegistered.compareAndSet(false, true)) {
+ DeviceConfig.addOnPropertiesChangedListener(NAMESPACE_SYSTEMUI, mExecutor,
+ mDeviceConfigChangedListener);
+ mTempAllowFgsLaunchDuration = DeviceConfig.getLong(NAMESPACE_SYSTEMUI,
+ PROPERTY_TILE_SERVICE_ONCLICK_ALLOW_LIST_DURATION,
+ TILE_SERVICE_ONCLICK_ALLOW_LIST_DEFAULT_DURATION_MS);
+ }
if (mBindTryCount == MAX_BIND_RETRIES) {
// Too many failures, give up on this tile until an update.
startPackageListening();
@@ -363,6 +390,9 @@
stopPackageListening();
}
mChangeListener = null;
+ if (mDeviceConfigChangedListener != null) {
+ DeviceConfig.removeOnPropertiesChangedListener(mDeviceConfigChangedListener);
+ }
}
/**
@@ -566,7 +596,17 @@
@Override
public void onClick(IBinder iBinder) {
if (mDebug) Log.d(TAG, "onClick " + iBinder + " " + getComponent() + " " + mUser);
- if (isNullOrFailedAction(mOptionalWrapper, (wrapper) -> wrapper.onClick(iBinder))) {
+ if (isNullOrFailedAction(mOptionalWrapper, (wrapper) -> {
+ final String packageName = mIntent.getComponent().getPackageName();
+ try {
+ mDeviceIdleController.addPowerSaveTempWhitelistApp(packageName,
+ mTempAllowFgsLaunchDuration, mUser.getIdentifier(), REASON_TILE_ONCLICK,
+ "tile onclick");
+ } catch (RemoteException e) {
+ Log.d(TAG, "Caught exception trying to add client package to temp allow list", e);
+ }
+ return wrapper.onClick(iBinder);
+ })) {
mClickBinder = iBinder;
queueMessage(MSG_ON_CLICK);
handleDeath();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/dagger/PanelsModule.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/dagger/PanelsModule.kt
index ee4eeb8..e3ba36f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/dagger/PanelsModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/dagger/PanelsModule.kt
@@ -18,20 +18,31 @@
import com.android.systemui.qs.panels.data.repository.IconTilesRepository
import com.android.systemui.qs.panels.data.repository.IconTilesRepositoryImpl
-import com.android.systemui.qs.panels.shared.model.GridLayoutTypeKey
+import com.android.systemui.qs.panels.shared.model.GridLayoutType
import com.android.systemui.qs.panels.shared.model.InfiniteGridLayoutType
import com.android.systemui.qs.panels.ui.compose.GridLayout
import com.android.systemui.qs.panels.ui.compose.InfiniteGridLayout
import dagger.Binds
import dagger.Module
-import dagger.multibindings.IntoMap
+import dagger.Provides
+import dagger.multibindings.IntoSet
@Module
interface PanelsModule {
@Binds fun bindIconTilesRepository(impl: IconTilesRepositoryImpl): IconTilesRepository
- @Binds
- @IntoMap
- @GridLayoutTypeKey(InfiniteGridLayoutType::class)
- fun bindGridLayout(impl: InfiniteGridLayout): GridLayout
+ companion object {
+ @Provides
+ @IntoSet
+ fun provideGridLayout(gridLayout: InfiniteGridLayout): Pair<GridLayoutType, GridLayout> {
+ return Pair(InfiniteGridLayoutType, gridLayout)
+ }
+
+ @Provides
+ fun provideGridLayoutMap(
+ entries: Set<@JvmSuppressWildcards Pair<GridLayoutType, GridLayout>>
+ ): Map<GridLayoutType, GridLayout> {
+ return entries.toMap()
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/GridLayout.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/GridLayout.kt
index 920cbe7..68ce5d8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/GridLayout.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/GridLayout.kt
@@ -25,6 +25,5 @@
fun TileGrid(
tiles: List<TileViewModel>,
modifier: Modifier,
- tile: @Composable (TileViewModel) -> Unit,
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/InfiniteGridLayout.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/InfiniteGridLayout.kt
index 4d0089e7..e2143e0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/InfiniteGridLayout.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/InfiniteGridLayout.kt
@@ -16,32 +16,77 @@
package com.android.systemui.qs.panels.ui.compose
+import android.graphics.drawable.Animatable
+import android.text.TextUtils
+import androidx.appcompat.content.res.AppCompatResources
+import androidx.compose.animation.graphics.ExperimentalAnimationGraphicsApi
+import androidx.compose.animation.graphics.res.animatedVectorResource
+import androidx.compose.animation.graphics.res.rememberAnimatedVectorPainter
+import androidx.compose.animation.graphics.vector.AnimatedImageVector
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.background
+import androidx.compose.foundation.basicMarquee
+import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.fillMaxHeight
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.GridItemSpan
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.collectAsState
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.ColorFilter
+import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.res.integerResource
+import com.android.compose.theme.colorAttr
+import com.android.systemui.common.shared.model.Icon
+import com.android.systemui.common.ui.compose.Icon
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.qs.panels.domain.interactor.IconTilesInteractor
+import com.android.systemui.qs.panels.ui.viewmodel.TileUiState
import com.android.systemui.qs.panels.ui.viewmodel.TileViewModel
+import com.android.systemui.qs.panels.ui.viewmodel.toUiState
+import com.android.systemui.qs.tileimpl.QSTileImpl
import com.android.systemui.res.R
import javax.inject.Inject
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.flow.mapLatest
-class InfiniteGridLayout @Inject constructor() : GridLayout {
+@SysUISingleton
+class InfiniteGridLayout @Inject constructor(private val iconTilesInteractor: IconTilesInteractor) :
+ GridLayout {
@Composable
override fun TileGrid(
tiles: List<TileViewModel>,
modifier: Modifier,
- tile: @Composable (TileViewModel) -> Unit
) {
DisposableEffect(tiles) {
val token = Any()
tiles.forEach { it.startListening(token) }
onDispose { tiles.forEach { it.stopListening(token) } }
}
+ val iconTilesSpecs by
+ iconTilesInteractor.iconTilesSpecs.collectAsState(initial = emptySet())
LazyVerticalGrid(
columns =
@@ -54,14 +99,128 @@
Arrangement.spacedBy(dimensionResource(R.dimen.qs_tile_margin_horizontal)),
modifier = modifier
) {
- tiles.forEach { item(span = { it.span() }) { tile(it) } }
+ items(
+ tiles.size,
+ span = { index ->
+ val iconOnly = iconTilesSpecs.contains(tiles[index].spec)
+ if (iconOnly) {
+ GridItemSpan(1)
+ } else {
+ GridItemSpan(2)
+ }
+ }
+ ) { index ->
+ Tile(
+ tiles[index],
+ iconTilesSpecs.contains(tiles[index].spec),
+ Modifier.height(dimensionResource(id = R.dimen.qs_tile_height))
+ )
+ }
}
}
- private fun TileViewModel.span(): GridItemSpan =
- if (iconOnly) {
- GridItemSpan(1)
- } else {
- GridItemSpan(2)
+ @OptIn(ExperimentalCoroutinesApi::class)
+ @Composable
+ private fun Tile(
+ tile: TileViewModel,
+ iconOnly: Boolean,
+ modifier: Modifier,
+ ) {
+ val state: TileUiState by
+ tile.state
+ .mapLatest { it.toUiState() }
+ .collectAsState(initial = tile.currentState.toUiState())
+ val context = LocalContext.current
+ val horizontalAlignment =
+ if (iconOnly) {
+ Alignment.CenterHorizontally
+ } else {
+ Alignment.Start
+ }
+
+ Row(
+ modifier =
+ modifier
+ .fillMaxWidth()
+ .clip(RoundedCornerShape(dimensionResource(R.dimen.qs_corner_radius)))
+ .clickable { tile.onClick(null) }
+ .background(colorAttr(state.colors.background))
+ .padding(
+ horizontal = dimensionResource(id = R.dimen.qs_label_container_margin)
+ ),
+ verticalAlignment = Alignment.CenterVertically,
+ horizontalArrangement =
+ Arrangement.spacedBy(
+ space = dimensionResource(id = R.dimen.qs_label_container_margin),
+ alignment = horizontalAlignment
+ )
+ ) {
+ val icon =
+ remember(state.icon) {
+ state.icon.get().let {
+ if (it is QSTileImpl.ResourceIcon) {
+ Icon.Resource(it.resId, null)
+ } else {
+ Icon.Loaded(it.getDrawable(context), null)
+ }
+ }
+ }
+ TileIcon(icon, colorAttr(state.colors.icon))
+
+ if (!iconOnly) {
+ Column(
+ verticalArrangement = Arrangement.Center,
+ modifier = Modifier.fillMaxHeight()
+ ) {
+ Text(
+ state.label.toString(),
+ color = colorAttr(state.colors.label),
+ modifier = Modifier.basicMarquee(),
+ )
+ if (!TextUtils.isEmpty(state.secondaryLabel)) {
+ Text(
+ state.secondaryLabel.toString(),
+ color = colorAttr(state.colors.secondaryLabel),
+ modifier = Modifier.basicMarquee(),
+ )
+ }
+ }
+ }
}
+ }
+
+ @OptIn(ExperimentalAnimationGraphicsApi::class)
+ @Composable
+ private fun TileIcon(icon: Icon, color: Color) {
+ val modifier = Modifier.size(dimensionResource(id = R.dimen.qs_icon_size))
+ val context = LocalContext.current
+ val loadedDrawable =
+ remember(icon, context) {
+ when (icon) {
+ is Icon.Loaded -> icon.drawable
+ is Icon.Resource -> AppCompatResources.getDrawable(context, icon.res)
+ }
+ }
+ if (loadedDrawable !is Animatable) {
+ Icon(
+ icon = icon,
+ tint = color,
+ modifier = modifier,
+ )
+ } else if (icon is Icon.Resource) {
+ val image = AnimatedImageVector.animatedVectorResource(id = icon.res)
+ var atEnd by remember(icon.res) { mutableStateOf(false) }
+ LaunchedEffect(key1 = icon.res) {
+ delay(350)
+ atEnd = true
+ }
+ val painter = rememberAnimatedVectorPainter(animatedImageVector = image, atEnd = atEnd)
+ Image(
+ painter = painter,
+ contentDescription = null,
+ colorFilter = ColorFilter.tint(color = color),
+ modifier = modifier
+ )
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/Tile.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/Tile.kt
deleted file mode 100644
index 35f2970..0000000
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/Tile.kt
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.qs.panels.ui.compose
-
-import android.graphics.drawable.Animatable
-import android.text.TextUtils
-import androidx.appcompat.content.res.AppCompatResources
-import androidx.compose.animation.graphics.ExperimentalAnimationGraphicsApi
-import androidx.compose.animation.graphics.res.animatedVectorResource
-import androidx.compose.animation.graphics.res.rememberAnimatedVectorPainter
-import androidx.compose.animation.graphics.vector.AnimatedImageVector
-import androidx.compose.foundation.Image
-import androidx.compose.foundation.background
-import androidx.compose.foundation.basicMarquee
-import androidx.compose.foundation.clickable
-import androidx.compose.foundation.layout.Arrangement
-import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.Row
-import androidx.compose.foundation.layout.fillMaxHeight
-import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.size
-import androidx.compose.foundation.shape.RoundedCornerShape
-import androidx.compose.material3.Text
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.runtime.collectAsState
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.setValue
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.draw.clip
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.ColorFilter
-import androidx.compose.ui.platform.LocalContext
-import androidx.compose.ui.res.dimensionResource
-import com.android.compose.theme.colorAttr
-import com.android.systemui.common.shared.model.Icon as IconModel
-import com.android.systemui.common.ui.compose.Icon
-import com.android.systemui.qs.panels.ui.viewmodel.TileUiState
-import com.android.systemui.qs.panels.ui.viewmodel.TileViewModel
-import com.android.systemui.qs.tileimpl.QSTileImpl
-import com.android.systemui.res.R
-import kotlinx.coroutines.delay
-
-@Composable
-fun Tile(
- tileViewModel: TileViewModel,
- modifier: Modifier = Modifier,
-) {
- val state: TileUiState by tileViewModel.state.collectAsState(tileViewModel.currentState)
- val context = LocalContext.current
- val horizontalAlignment =
- if (state.iconOnly) {
- Alignment.CenterHorizontally
- } else {
- Alignment.Start
- }
-
- Row(
- modifier =
- modifier
- .fillMaxWidth()
- .clip(RoundedCornerShape(dimensionResource(R.dimen.qs_corner_radius)))
- .clickable { tileViewModel.onClick(null) }
- .background(colorAttr(state.colors.background))
- .padding(horizontal = dimensionResource(id = R.dimen.qs_label_container_margin)),
- verticalAlignment = Alignment.CenterVertically,
- horizontalArrangement =
- Arrangement.spacedBy(
- space = dimensionResource(id = R.dimen.qs_label_container_margin),
- alignment = horizontalAlignment
- )
- ) {
- val icon =
- remember(state.icon) {
- state.icon.get().let {
- if (it is QSTileImpl.ResourceIcon) {
- IconModel.Resource(it.resId, null)
- } else {
- IconModel.Loaded(it.getDrawable(context), null)
- }
- }
- }
- TileIcon(icon, colorAttr(state.colors.icon))
-
- if (!state.iconOnly) {
- Column(verticalArrangement = Arrangement.Center, modifier = Modifier.fillMaxHeight()) {
- Text(
- state.label.toString(),
- color = colorAttr(state.colors.label),
- modifier = Modifier.basicMarquee(),
- )
- if (!TextUtils.isEmpty(state.secondaryLabel)) {
- Text(
- state.secondaryLabel.toString(),
- color = colorAttr(state.colors.secondaryLabel),
- modifier = Modifier.basicMarquee(),
- )
- }
- }
- }
- }
-}
-
-@OptIn(ExperimentalAnimationGraphicsApi::class)
-@Composable
-private fun TileIcon(icon: IconModel, color: Color) {
- val modifier = Modifier.size(dimensionResource(id = R.dimen.qs_icon_size))
- val context = LocalContext.current
- val loadedDrawable =
- remember(icon, context) {
- when (icon) {
- is IconModel.Loaded -> icon.drawable
- is IconModel.Resource -> AppCompatResources.getDrawable(context, icon.res)
- }
- }
- if (loadedDrawable !is Animatable) {
- Icon(
- icon = icon,
- tint = color,
- modifier = modifier,
- )
- } else if (icon is IconModel.Resource) {
- val image = AnimatedImageVector.animatedVectorResource(id = icon.res)
- var atEnd by remember(icon.res) { mutableStateOf(false) }
- LaunchedEffect(key1 = icon.res) {
- delay(350)
- atEnd = true
- }
- val painter = rememberAnimatedVectorPainter(animatedImageVector = image, atEnd = atEnd)
- Image(
- painter = painter,
- contentDescription = null,
- colorFilter = ColorFilter.tint(color = color),
- modifier = modifier
- )
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/TileGrid.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/TileGrid.kt
index a528eed..2f32d72 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/TileGrid.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/TileGrid.kt
@@ -16,21 +16,16 @@
package com.android.systemui.qs.panels.ui.compose
-import androidx.compose.foundation.layout.height
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
-import androidx.compose.ui.res.dimensionResource
import com.android.systemui.qs.panels.ui.viewmodel.TileGridViewModel
-import com.android.systemui.res.R
@Composable
fun TileGrid(viewModel: TileGridViewModel, modifier: Modifier = Modifier) {
- val gridLayout by viewModel.gridLayout.collectAsState(InfiniteGridLayout())
+ val gridLayout by viewModel.gridLayout.collectAsState()
val tiles by viewModel.tileViewModels.collectAsState(emptyList())
- gridLayout.TileGrid(tiles, modifier) {
- Tile(it, modifier = Modifier.height(dimensionResource(id = R.dimen.qs_tile_height)))
- }
+ gridLayout.TileGrid(tiles, modifier)
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/TileGridViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/TileGridViewModel.kt
index fc13460..5eee691 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/TileGridViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/TileGridViewModel.kt
@@ -17,34 +17,39 @@
package com.android.systemui.qs.panels.ui.viewmodel
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.qs.panels.domain.interactor.GridLayoutTypeInteractor
-import com.android.systemui.qs.panels.domain.interactor.IconTilesInteractor
import com.android.systemui.qs.panels.shared.model.GridLayoutType
import com.android.systemui.qs.panels.ui.compose.GridLayout
import com.android.systemui.qs.panels.ui.compose.InfiniteGridLayout
import com.android.systemui.qs.pipeline.domain.interactor.CurrentTilesInteractor
import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.mapLatest
+import kotlinx.coroutines.flow.stateIn
+@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class TileGridViewModel
@Inject
constructor(
gridLayoutTypeInteractor: GridLayoutTypeInteractor,
- gridLayoutMap: Map<Class<out GridLayoutType>, @JvmSuppressWildcards GridLayout>,
+ gridLayoutMap: Map<GridLayoutType, @JvmSuppressWildcards GridLayout>,
tilesInteractor: CurrentTilesInteractor,
- iconTilesInteractor: IconTilesInteractor,
+ defaultGridLayout: InfiniteGridLayout,
+ @Application private val applicationScope: CoroutineScope
) {
- val gridLayout: Flow<GridLayout> =
- gridLayoutTypeInteractor.layout.map {
- gridLayoutMap[it::class.java] ?: InfiniteGridLayout()
- }
+ val gridLayout: StateFlow<GridLayout> =
+ gridLayoutTypeInteractor.layout
+ .map { gridLayoutMap[it] ?: defaultGridLayout }
+ .stateIn(applicationScope, SharingStarted.Eagerly, defaultGridLayout)
val tileViewModels: Flow<List<TileViewModel>> =
- combine(tilesInteractor.currentTiles, iconTilesInteractor.iconTilesSpecs) {
- tiles,
- iconTilesSpecs ->
- tiles.map { TileViewModel(it.tile, iconTilesSpecs.contains(it.spec)) }
+ tilesInteractor.currentTiles.mapLatest { tiles ->
+ tiles.map { TileViewModel(it.tile, it.spec) }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/TileUiState.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/TileUiState.kt
index f4b7255..58d07c3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/TileUiState.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/TileUiState.kt
@@ -24,15 +24,13 @@
val secondaryLabel: CharSequence,
val colors: TileColorAttributes,
val icon: Supplier<QSTile.Icon>,
- val iconOnly: Boolean,
)
-fun QSTile.State.toUiState(iconOnly: Boolean): TileUiState {
+fun QSTile.State.toUiState(): TileUiState {
return TileUiState(
label ?: "",
secondaryLabel ?: "",
colors(),
icon?.let { Supplier { icon } } ?: iconSupplier,
- iconOnly,
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/TileViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/TileViewModel.kt
index 08e9119..a6cfa75 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/TileViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/TileViewModel.kt
@@ -16,19 +16,17 @@
package com.android.systemui.qs.panels.ui.viewmodel
-import android.view.View
-import android.view.View.OnLongClickListener
+import com.android.systemui.animation.Expandable
import com.android.systemui.plugins.qs.QSTile
+import com.android.systemui.qs.pipeline.shared.TileSpec
import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.distinctUntilChanged
-import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onStart
-class TileViewModel(private val tile: QSTile, val iconOnly: Boolean = false) :
- OnLongClickListener, View.OnClickListener {
- val state: Flow<TileUiState> =
+class TileViewModel(private val tile: QSTile, val spec: TileSpec) {
+ val state: Flow<QSTile.State> =
conflatedCallbackFlow {
val callback = QSTile.Callback { trySend(it.copy()) }
@@ -37,19 +35,17 @@
awaitClose { tile.removeCallback(callback) }
}
.onStart { emit(tile.state) }
- .map { it.toUiState(iconOnly) }
.distinctUntilChanged()
- val currentState: TileUiState
- get() = tile.state.toUiState(iconOnly)
+ val currentState: QSTile.State
+ get() = tile.state
- override fun onClick(view: View?) {
- tile.click(view)
+ fun onClick(expandable: Expandable?) {
+ tile.click(expandable)
}
- override fun onLongClick(view: View?): Boolean {
- tile.longClick(view)
- return true
+ fun onLongClick(expandable: Expandable?) {
+ tile.longClick(expandable)
}
fun startListening(token: Any) = tile.setListening(token, true)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/InstalledTilesComponentRepository.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/InstalledTilesComponentRepository.kt
index 93021ba..cfcea98 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/InstalledTilesComponentRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/InstalledTilesComponentRepository.kt
@@ -91,7 +91,15 @@
.queryIntentServicesAsUser(INTENT, FLAGS, userId)
.mapNotNull { it.serviceInfo }
.filter { it.permission == BIND_QUICK_SETTINGS_TILE }
- .filter { packageManager.isComponentActuallyEnabled(it) }
+ .filter {
+ try {
+ packageManager.isComponentActuallyEnabled(it)
+ } catch (e: IllegalArgumentException) {
+ // If the package is not found, it means it was uninstalled between query
+ // and now. So it's clearly not enabled.
+ false
+ }
+ }
.mapTo(mutableSetOf()) { it.componentName }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSLongPressProperties.kt b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSLongPressProperties.kt
index a2ded6a..71cf9e6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSLongPressProperties.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSLongPressProperties.kt
@@ -22,8 +22,8 @@
* These properties are used during animation if a tile supports a long-press action.
*/
data class QSLongPressProperties(
- var xScale: Float,
- var yScale: Float,
+ var height: Float,
+ var width: Float,
var cornerRadius: Float,
var backgroundColor: Int,
var labelColor: Int,
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
index 1456747..c24113f1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
@@ -42,7 +42,6 @@
import android.util.ArraySet;
import android.util.Log;
import android.util.SparseArray;
-import android.view.View;
import androidx.annotation.Nullable;
import androidx.lifecycle.Lifecycle;
@@ -58,6 +57,7 @@
import com.android.settingslib.RestrictedLockUtilsInternal;
import com.android.systemui.Dumpable;
import com.android.systemui.animation.ActivityTransitionAnimator;
+import com.android.systemui.animation.Expandable;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.qs.QSTile;
@@ -137,9 +137,9 @@
*
* Calls to the controller should be made here to set the new state of the device.
*
- * @param view The view that was clicked.
+ * @param expandable {@link Expandable} that was clicked.
*/
- protected abstract void handleClick(@Nullable View view);
+ protected abstract void handleClick(@Nullable Expandable expandable);
/**
* Update state of the tile based on device state
@@ -282,7 +282,8 @@
mHandler.sendEmptyMessage(H.REMOVE_CALLBACKS);
}
- public void click(@Nullable View view) {
+ @Override
+ public void click(@Nullable Expandable expandable) {
mMetricsLogger.write(populate(new LogMaker(ACTION_QS_CLICK).setType(TYPE_ACTION)
.addTaggedData(FIELD_STATUS_BAR_STATE,
mStatusBarStateController.getState())));
@@ -292,11 +293,12 @@
mQSLogger.logTileClick(mTileSpec, mStatusBarStateController.getState(), mState.state,
eventId);
if (!mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
- mHandler.obtainMessage(H.CLICK, eventId, 0, view).sendToTarget();
+ mHandler.obtainMessage(H.CLICK, eventId, 0, expandable).sendToTarget();
}
}
- public void secondaryClick(@Nullable View view) {
+ @Override
+ public void secondaryClick(@Nullable Expandable expandable) {
mMetricsLogger.write(populate(new LogMaker(ACTION_QS_SECONDARY_CLICK).setType(TYPE_ACTION)
.addTaggedData(FIELD_STATUS_BAR_STATE,
mStatusBarStateController.getState())));
@@ -305,11 +307,11 @@
final int eventId = mClickEventId++;
mQSLogger.logTileSecondaryClick(mTileSpec, mStatusBarStateController.getState(),
mState.state, eventId);
- mHandler.obtainMessage(H.SECONDARY_CLICK, eventId, 0, view).sendToTarget();
+ mHandler.obtainMessage(H.SECONDARY_CLICK, eventId, 0, expandable).sendToTarget();
}
@Override
- public void longClick(@Nullable View view) {
+ public void longClick(@Nullable Expandable expandable) {
mMetricsLogger.write(populate(new LogMaker(ACTION_QS_LONG_PRESS).setType(TYPE_ACTION)
.addTaggedData(FIELD_STATUS_BAR_STATE,
mStatusBarStateController.getState())));
@@ -319,7 +321,7 @@
mQSLogger.logTileLongClick(mTileSpec, mStatusBarStateController.getState(), mState.state,
eventId);
if (!mFalsingManager.isFalseLongTap(FalsingManager.LOW_PENALTY)) {
- mHandler.obtainMessage(H.LONG_CLICK, eventId, 0, view).sendToTarget();
+ mHandler.obtainMessage(H.LONG_CLICK, eventId, 0, expandable).sendToTarget();
}
}
@@ -397,22 +399,22 @@
*
* Defaults to {@link QSTileImpl#handleClick}
*
- * @param view The view that was clicked.
+ * @param expandable {@link Expandable} that was clicked.
*/
- protected void handleSecondaryClick(@Nullable View view) {
+ protected void handleSecondaryClick(@Nullable Expandable expandable) {
// Default to normal click.
- handleClick(view);
+ handleClick(expandable);
}
/**
* Handles long click on the tile by launching the {@link Intent} defined in
* {@link QSTileImpl#getLongClickIntent}.
*
- * @param view The view from which the opening window will be animated.
+ * @param expandable {@link Expandable} from which the opening window will be animated.
*/
- protected void handleLongClick(@Nullable View view) {
+ protected void handleLongClick(@Nullable Expandable expandable) {
ActivityTransitionAnimator.Controller animationController =
- view != null ? ActivityTransitionAnimator.Controller.fromView(view,
+ expandable != null ? expandable.activityTransitionController(
InteractionJankMonitor.CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE) : null;
mActivityStarter.postStartActivityDismissingKeyguard(getLongClickIntent(), 0,
animationController);
@@ -591,16 +593,16 @@
mActivityStarter.postStartActivityDismissingKeyguard(intent, 0);
} else {
mQSLogger.logHandleClick(mTileSpec, msg.arg1);
- handleClick((View) msg.obj);
+ handleClick((Expandable) msg.obj);
}
} else if (msg.what == SECONDARY_CLICK) {
name = "handleSecondaryClick";
mQSLogger.logHandleSecondaryClick(mTileSpec, msg.arg1);
- handleSecondaryClick((View) msg.obj);
+ handleSecondaryClick((Expandable) msg.obj);
} else if (msg.what == LONG_CLICK) {
name = "handleLongClick";
mQSLogger.logHandleLongClick(mTileSpec, msg.arg1);
- handleLongClick((View) msg.obj);
+ handleLongClick((Expandable) msg.obj);
} else if (msg.what == REFRESH_STATE) {
name = "handleRefreshState";
handleRefreshState(msg.obj);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
index 40cf4a4..4fd0df4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
@@ -25,6 +25,7 @@
import android.content.res.Resources.ID_NULL
import android.graphics.Color
import android.graphics.PorterDuff
+import android.graphics.Rect
import android.graphics.drawable.Drawable
import android.graphics.drawable.GradientDrawable
import android.graphics.drawable.LayerDrawable
@@ -46,11 +47,13 @@
import android.widget.Switch
import android.widget.TextView
import androidx.annotation.VisibleForTesting
+import androidx.core.graphics.drawable.updateBounds
import com.android.app.tracing.traceSection
import com.android.settingslib.Utils
import com.android.systemui.Flags
import com.android.systemui.Flags.quickSettingsVisualHapticsLongpress
import com.android.systemui.FontSizeUtils
+import com.android.systemui.animation.Expandable
import com.android.systemui.animation.LaunchableView
import com.android.systemui.animation.LaunchableViewDelegate
import com.android.systemui.haptics.qs.QSLongPressEffect
@@ -62,7 +65,6 @@
import com.android.systemui.qs.logging.QSLogger
import com.android.systemui.qs.tileimpl.QSIconViewImpl.QS_ANIM_LENGTH
import com.android.systemui.res.R
-import com.android.systemui.util.children
import kotlinx.coroutines.DisposableHandle
import java.util.Objects
@@ -83,6 +85,10 @@
const val UNAVAILABLE_ALPHA = 0.3f
@VisibleForTesting
internal const val TILE_STATE_RES_PREFIX = "tile_states_"
+ @VisibleForTesting
+ internal const val LONG_PRESS_EFFECT_WIDTH_SCALE = 1.1f
+ @VisibleForTesting
+ internal const val LONG_PRESS_EFFECT_HEIGHT_SCALE = 1.2f
}
private val icon: QSIconViewImpl = QSIconViewImpl(context)
@@ -180,6 +186,9 @@
private val locInScreen = IntArray(2)
/** Visuo-haptic long-press effects */
+ var haveLongPressPropertiesBeenReset = true
+ private set
+ private var paddingForLaunch = Rect()
private var initialLongPressProperties: QSLongPressProperties? = null
private var finalLongPressProperties: QSLongPressProperties? = null
private val colorEvaluator = ArgbEvaluator.getInstance()
@@ -326,7 +335,7 @@
private fun updateHeight() {
// TODO(b/332900989): Find a more robust way of resetting the tile if not reset by the
// launch animation.
- if (scaleX != 1f || scaleY != 1f) {
+ if (!haveLongPressPropertiesBeenReset && longPressEffect != null) {
// The launch animation of a long-press effect did not reset the long-press effect so
// we must do it here
resetLongPressEffectProperties()
@@ -357,10 +366,11 @@
}
override fun init(tile: QSTile) {
+ val expandable = Expandable.fromView(this)
init(
- { v: View? -> tile.click(this) },
- { view: View? ->
- tile.longClick(this)
+ { _: View? -> tile.click(expandable) },
+ { _: View? ->
+ tile.longClick(expandable)
true
}
)
@@ -632,7 +642,7 @@
)
}
showRippleEffect = false
- initializeLongPressProperties()
+ initializeLongPressProperties(measuredHeight, measuredWidth)
} else {
// Long-press effects might have been enabled before but the new state does not
// handle a long-press. In this case, we go back to the behaviour of a regular tile
@@ -763,10 +773,66 @@
}
}
- override fun onActivityLaunchAnimationEnd() = resetLongPressEffectProperties()
+ override fun onActivityLaunchAnimationEnd() {
+ if (longPressEffect != null && !haveLongPressPropertiesBeenReset) {
+ resetLongPressEffectProperties()
+ }
+ }
+
+ fun prepareForLaunch() {
+ val startingHeight = initialLongPressProperties?.height?.toInt() ?: 0
+ val startingWidth = initialLongPressProperties?.width?.toInt() ?: 0
+ val deltaH = finalLongPressProperties?.height?.minus(startingHeight)?.toInt() ?: 0
+ val deltaW = finalLongPressProperties?.width?.minus(startingWidth)?.toInt() ?: 0
+ paddingForLaunch.left = -deltaW / 2
+ paddingForLaunch.top = -deltaH / 2
+ paddingForLaunch.right = deltaW / 2
+ paddingForLaunch.bottom = deltaH / 2
+ }
+
+ override fun getPaddingForLaunchAnimation(): Rect = paddingForLaunch
fun updateLongPressEffectProperties(effectProgress: Float) {
if (!isLongClickable || longPressEffect == null) return
+
+ if (haveLongPressPropertiesBeenReset) haveLongPressPropertiesBeenReset = false
+
+ // Dimensions change
+ val newHeight =
+ interpolateFloat(
+ effectProgress,
+ initialLongPressProperties?.height ?: 0f,
+ finalLongPressProperties?.height ?: 0f,
+ ).toInt()
+ val newWidth =
+ interpolateFloat(
+ effectProgress,
+ initialLongPressProperties?.width ?: 0f,
+ finalLongPressProperties?.width ?: 0f,
+ ).toInt()
+
+ val startingHeight = initialLongPressProperties?.height?.toInt() ?: 0
+ val startingWidth = initialLongPressProperties?.width?.toInt() ?: 0
+ val deltaH = (newHeight - startingHeight) / 2
+ val deltaW = (newWidth - startingWidth) / 2
+
+ background.updateBounds(
+ left = -deltaW,
+ top = -deltaH,
+ right = newWidth - deltaW,
+ bottom = newHeight - deltaH,
+ )
+
+ // Radius change
+ val newRadius =
+ interpolateFloat(
+ effectProgress,
+ initialLongPressProperties?.cornerRadius ?: 0f,
+ finalLongPressProperties?.cornerRadius ?: 0f,
+ )
+ changeCornerRadius(newRadius)
+
+ // Color change
setAllColors(
colorEvaluator.evaluate(
effectProgress,
@@ -802,32 +868,6 @@
finalLongPressProperties?.iconColor ?: 0,
) as Int,
)
-
- val newScaleX =
- interpolateFloat(
- effectProgress,
- initialLongPressProperties?.xScale ?: 1f,
- finalLongPressProperties?.xScale ?: 1f,
- )
- val newScaleY =
- interpolateFloat(
- effectProgress,
- initialLongPressProperties?.xScale ?: 1f,
- finalLongPressProperties?.xScale ?: 1f,
- )
- val newRadius =
- interpolateFloat(
- effectProgress,
- initialLongPressProperties?.cornerRadius ?: 0f,
- finalLongPressProperties?.cornerRadius ?: 0f,
- )
- scaleX = newScaleX
- scaleY = newScaleY
- for (child in children) {
- child.scaleX = 1f / newScaleX
- child.scaleY = 1f / newScaleY
- }
- changeCornerRadius(newRadius)
}
private fun unbindLongPressEffect() {
@@ -839,12 +879,12 @@
start + fraction * (end - start)
fun resetLongPressEffectProperties() {
- scaleY = 1f
- scaleX = 1f
- for (child in children) {
- child.scaleY = 1f
- child.scaleX = 1f
- }
+ background.updateBounds(
+ left = 0,
+ top = 0,
+ right = initialLongPressProperties?.width?.toInt() ?: measuredWidth,
+ bottom = initialLongPressProperties?.height?.toInt() ?: measuredHeight,
+ )
changeCornerRadius(resources.getDimensionPixelSize(R.dimen.qs_corner_radius).toFloat())
setAllColors(
getBackgroundColorForState(lastState, lastDisabledByPolicy),
@@ -854,13 +894,15 @@
getOverlayColorForState(lastState),
)
icon.setTint(icon.mIcon as ImageView, lastIconTint)
+ haveLongPressPropertiesBeenReset = true
}
- private fun initializeLongPressProperties() {
+ @VisibleForTesting
+ fun initializeLongPressProperties(startingHeight: Int, startingWidth: Int) {
initialLongPressProperties =
QSLongPressProperties(
- /* xScale= */1f,
- /* yScale= */1f,
+ height = startingHeight.toFloat(),
+ width = startingWidth.toFloat(),
resources.getDimensionPixelSize(R.dimen.qs_corner_radius).toFloat(),
getBackgroundColorForState(lastState),
getLabelColorForState(lastState),
@@ -872,8 +914,8 @@
finalLongPressProperties =
QSLongPressProperties(
- /* xScale= */1.1f,
- /* yScale= */1.2f,
+ height = LONG_PRESS_EFFECT_HEIGHT_SCALE * startingHeight,
+ width = LONG_PRESS_EFFECT_WIDTH_SCALE * startingWidth,
resources.getDimensionPixelSize(R.dimen.qs_corner_radius).toFloat() - 20,
getBackgroundColorForState(Tile.STATE_ACTIVE),
getLabelColorForState(Tile.STATE_ACTIVE),
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
index 17251c3..2068799 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
@@ -29,13 +29,13 @@
import android.service.quicksettings.Tile;
import android.sysprop.TelephonyProperties;
import android.telephony.TelephonyManager;
-import android.view.View;
import android.widget.Switch;
import androidx.annotation.Nullable;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.systemui.animation.Expandable;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
@@ -103,7 +103,7 @@
}
@Override
- public void handleClick(@Nullable View view) {
+ public void handleClick(@Nullable Expandable expandable) {
boolean airplaneModeEnabled = mState.value;
MetricsLogger.action(mContext, getMetricsCategory(), !airplaneModeEnabled);
if (!airplaneModeEnabled && TelephonyProperties.in_ecm_mode().orElse(false)) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AlarmTile.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/AlarmTile.kt
index 688f3ca..73d991f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AlarmTile.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AlarmTile.kt
@@ -9,12 +9,10 @@
import android.service.quicksettings.Tile
import android.text.TextUtils
import android.text.format.DateFormat
-import android.view.View
import androidx.annotation.VisibleForTesting
import com.android.internal.jank.InteractionJankMonitor
import com.android.internal.logging.MetricsLogger
-import com.android.systemui.res.R
-import com.android.systemui.animation.ActivityTransitionAnimator
+import com.android.systemui.animation.Expandable
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.plugins.ActivityStarter
@@ -25,12 +23,15 @@
import com.android.systemui.qs.QsEventLogger
import com.android.systemui.qs.logging.QSLogger
import com.android.systemui.qs.tileimpl.QSTileImpl
+import com.android.systemui.res.R
import com.android.systemui.settings.UserTracker
import com.android.systemui.statusbar.policy.NextAlarmController
import java.util.Locale
import javax.inject.Inject
-class AlarmTile @Inject constructor(
+class AlarmTile
+@Inject
+constructor(
host: QSHost,
uiEventLogger: QsEventLogger,
@Background backgroundLooper: Looper,
@@ -56,8 +57,7 @@
private var lastAlarmInfo: AlarmManager.AlarmClockInfo? = null
private val icon = ResourceIcon.get(R.drawable.ic_alarm)
- @VisibleForTesting
- internal val defaultIntent = Intent(AlarmClock.ACTION_SHOW_ALARMS)
+ @VisibleForTesting internal val defaultIntent = Intent(AlarmClock.ACTION_SHOW_ALARMS)
private val callback = NextAlarmController.NextAlarmChangeCallback { nextAlarm ->
lastAlarmInfo = nextAlarm
refreshState()
@@ -73,11 +73,11 @@
}
}
- override fun handleClick(view: View?) {
- val animationController = view?.let {
- ActivityTransitionAnimator.Controller.fromView(
- it, InteractionJankMonitor.CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE)
- }
+ override fun handleClick(expandable: Expandable?) {
+ val animationController =
+ expandable?.activityTransitionController(
+ InteractionJankMonitor.CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE
+ )
val pendingIntent = lastAlarmInfo?.showIntent
if (pendingIntent != null) {
mActivityStarter.postStartActivityDismissingKeyguard(pendingIntent, animationController)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
index 426aa55..7c0ce4c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
@@ -21,7 +21,6 @@
import android.provider.Settings;
import android.provider.Settings.Secure;
import android.service.quicksettings.Tile;
-import android.view.View;
import android.widget.Switch;
import androidx.annotation.Nullable;
@@ -29,6 +28,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.systemui.animation.Expandable;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
@@ -121,7 +121,7 @@
if (!listening) {
// If we stopped listening, it means that the tile is not visible. In that case, we
// don't need to save the view anymore
- mBatteryController.clearLastPowerSaverStartView();
+ mBatteryController.clearLastPowerSaverStartExpandable();
}
}
@@ -131,11 +131,11 @@
}
@Override
- protected void handleClick(@Nullable View view) {
+ protected void handleClick(@Nullable Expandable expandable) {
if (getState().state == Tile.STATE_UNAVAILABLE) {
return;
}
- mBatteryController.setPowerSaveMode(!mPowerSave, view);
+ mBatteryController.setPowerSaveMode(!mPowerSave, expandable);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index 6eae32a..9af34f6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -31,7 +31,6 @@
import android.service.quicksettings.Tile;
import android.text.TextUtils;
import android.util.Log;
-import android.view.View;
import android.widget.Switch;
import com.android.internal.logging.MetricsLogger;
@@ -39,6 +38,7 @@
import com.android.settingslib.Utils;
import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.systemui.animation.Expandable;
import com.android.systemui.bluetooth.qsdialog.BluetoothTileDialogViewModel;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
@@ -109,9 +109,9 @@
}
@Override
- protected void handleClick(@Nullable View view) {
+ protected void handleClick(@Nullable Expandable expandable) {
if (mFeatureFlags.isEnabled(Flags.BLUETOOTH_QS_TILE_DIALOG)) {
- mDialogViewModel.showDialog(view);
+ mDialogViewModel.showDialog(expandable);
} else {
// Secondary clicks are header clicks, just toggle.
final boolean isEnabled = mState.value;
@@ -127,7 +127,7 @@
}
@Override
- protected void handleSecondaryClick(@Nullable View view) {
+ protected void handleSecondaryClick(@Nullable Expandable expandable) {
if (!mController.canConfigBluetooth()) {
mActivityStarter.postStartActivityDismissingKeyguard(
new Intent(Settings.ACTION_BLUETOOTH_SETTINGS), 0);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
index b27b974..169cdc1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -29,7 +29,6 @@
import android.provider.Settings;
import android.service.quicksettings.Tile;
import android.util.Log;
-import android.view.View;
import android.widget.Button;
import androidx.annotation.Nullable;
@@ -41,6 +40,7 @@
import com.android.systemui.animation.ActivityTransitionAnimator;
import com.android.systemui.animation.DialogCuj;
import com.android.systemui.animation.DialogTransitionAnimator;
+import com.android.systemui.animation.Expandable;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.flags.FeatureFlags;
@@ -161,12 +161,12 @@
}
@Override
- protected void handleLongClick(@Nullable View view) {
- handleClick(view);
+ protected void handleLongClick(@Nullable Expandable expandable) {
+ handleClick(expandable);
}
@Override
- protected void handleClick(@Nullable View view) {
+ protected void handleClick(@Nullable Expandable expandable) {
if (getState().state == Tile.STATE_UNAVAILABLE) {
return;
}
@@ -174,7 +174,7 @@
List<CastDevice> activeDevices = getActiveDevices();
if (willPopDialog()) {
if (!mKeyguard.isShowing()) {
- showDialog(view);
+ showDialog(expandable);
} else {
mActivityStarter.postQSRunnableDismissingKeyguard(() -> {
// Dismissing the keyguard will collapse the shade, so we don't animate from the
@@ -216,7 +216,7 @@
}
}
- private void showDialog(@Nullable View view) {
+ private void showDialog(@Nullable Expandable expandable) {
mUiHandler.post(() -> {
final DialogHolder holder = new DialogHolder();
final Dialog dialog = MediaRouteDialogPresenter.createDialog(
@@ -241,17 +241,21 @@
SystemUIDialog.setDialogSize(dialog);
mUiHandler.post(() -> {
- if (view != null) {
- mDialogTransitionAnimator.showFromView(dialog, view,
- new DialogCuj(InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN,
- INTERACTION_JANK_TAG));
- } else {
- if (dialog.getWindow() != null) {
- DialogKt.registerAnimationOnBackInvoked(dialog,
- dialog.getWindow().getDecorView());
+ if (expandable != null) {
+ DialogTransitionAnimator.Controller controller =
+ expandable.dialogTransitionController(
+ new DialogCuj(InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN,
+ INTERACTION_JANK_TAG));
+ if (controller != null) {
+ mDialogTransitionAnimator.show(dialog, controller);
+ return;
}
- dialog.show();
}
+ if (dialog.getWindow() != null) {
+ DialogKt.registerAnimationOnBackInvoked(dialog,
+ dialog.getWindow().getDecorView());
+ }
+ dialog.show();
});
});
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorCorrectionTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorCorrectionTile.java
index c8adbfc..871973df 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorCorrectionTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorCorrectionTile.java
@@ -22,12 +22,12 @@
import android.provider.Settings;
import android.provider.Settings.Secure;
import android.service.quicksettings.Tile;
-import android.view.View;
import android.widget.Switch;
import androidx.annotation.Nullable;
import com.android.internal.logging.MetricsLogger;
+import com.android.systemui.animation.Expandable;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
@@ -109,7 +109,7 @@
}
@Override
- protected void handleClick(@Nullable View view) {
+ protected void handleClick(@Nullable Expandable expandable) {
mSetting.setValue(mState.value ? 0 : 1);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
index c34a584..5896910 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
@@ -22,13 +22,13 @@
import android.provider.Settings;
import android.provider.Settings.Secure;
import android.service.quicksettings.Tile;
-import android.view.View;
import android.widget.Switch;
import androidx.annotation.Nullable;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.systemui.animation.Expandable;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
@@ -108,7 +108,7 @@
}
@Override
- protected void handleClick(@Nullable View view) {
+ protected void handleClick(@Nullable Expandable expandable) {
mSetting.setValue(mState.value ? 0 : 1);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
index 58630a0..7760943 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
@@ -19,7 +19,6 @@
import android.os.Looper;
import android.provider.Settings;
import android.service.quicksettings.Tile;
-import android.view.View;
import android.widget.Switch;
import androidx.annotation.Nullable;
@@ -30,6 +29,7 @@
import com.android.systemui.Prefs;
import com.android.systemui.animation.DialogCuj;
import com.android.systemui.animation.DialogTransitionAnimator;
+import com.android.systemui.animation.Expandable;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
@@ -47,7 +47,7 @@
import javax.inject.Inject;
public class DataSaverTile extends QSTileImpl<BooleanState> implements
- DataSaverController.Listener{
+ DataSaverController.Listener {
public static final String TILE_SPEC = "saver";
@@ -89,8 +89,9 @@
public Intent getLongClickIntent() {
return new Intent(Settings.ACTION_DATA_SAVER_SETTINGS);
}
+
@Override
- protected void handleClick(@Nullable View view) {
+ protected void handleClick(@Nullable Expandable expandable) {
if (mState.value
|| Prefs.getBoolean(mContext, Prefs.Key.QS_DATA_SAVER_DIALOG_SHOWN, false)) {
// Do it right away.
@@ -112,10 +113,16 @@
dialog.setNeutralButton(com.android.internal.R.string.cancel, null);
dialog.setShowForAllUsers(true);
- if (view != null) {
- mDialogTransitionAnimator.showFromView(dialog, view, new DialogCuj(
- InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN,
- INTERACTION_JANK_TAG));
+ if (expandable != null) {
+ DialogTransitionAnimator.Controller controller =
+ expandable.dialogTransitionController(new DialogCuj(
+ InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN,
+ INTERACTION_JANK_TAG));
+ if (controller != null) {
+ mDialogTransitionAnimator.show(dialog, controller);
+ } else {
+ dialog.show();
+ }
} else {
dialog.show();
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt
index bb175e2..cc8a734 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt
@@ -1,3 +1,4 @@
+
/*
* Copyright (C) 2021 The Android Open Source Project
*
@@ -21,12 +22,11 @@
import android.os.Handler
import android.os.Looper
import android.service.quicksettings.Tile
-import android.view.View
import androidx.annotation.VisibleForTesting
import com.android.internal.jank.InteractionJankMonitor
import com.android.internal.logging.MetricsLogger
import com.android.systemui.res.R
-import com.android.systemui.animation.ActivityTransitionAnimator
+import com.android.systemui.animation.Expandable
import com.android.systemui.controls.ControlsServiceInfo
import com.android.systemui.controls.dagger.ControlsComponent
import com.android.systemui.controls.dagger.ControlsComponent.Visibility.AVAILABLE
@@ -100,26 +100,30 @@
}
}
- override fun handleClick(view: View?) {
+ override fun handleClick(expandable: Expandable?) {
if (state.state == Tile.STATE_UNAVAILABLE) {
return
}
val intent = Intent().apply {
component = ComponentName(mContext, controlsComponent.getControlsUiController().get()
- .resolveActivity())
+ .resolveActivity())
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK)
putExtra(ControlsUiController.EXTRA_ANIMATE, true)
}
- val animationController = view?.let {
- ActivityTransitionAnimator.Controller.fromView(
- it, InteractionJankMonitor.CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE)
- }
+ val animationController =
+ expandable?.activityTransitionController(
+ InteractionJankMonitor.CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE
+ )
mUiHandler.post {
val showOverLockscreenWhenLocked = state.state == Tile.STATE_ACTIVE
mActivityStarter.startActivity(
- intent, true /* dismissShade */, animationController, showOverLockscreenWhenLocked)
+ intent,
+ true /* dismissShade */,
+ animationController,
+ showOverLockscreenWhenLocked,
+ )
}
}
@@ -130,7 +134,7 @@
if (controlsComponent.isEnabled() && hasControlsApps.get()) {
if (controlsComponent.getVisibility() == AVAILABLE) {
val selection = controlsComponent
- .getControlsController().get().getPreferredSelection()
+ .getControlsController().get().getPreferredSelection()
state.state = if (selection is SelectedItem.StructureItem &&
selection.structure.controls.isEmpty()) {
Tile.STATE_INACTIVE
@@ -157,7 +161,7 @@
return null
}
- override fun handleLongClick(view: View?) {}
+ override fun handleLongClick(expandable: Expandable?) {}
override fun getTileLabel(): CharSequence {
return mContext.getText(controlsComponent.getTileTitleId())
@@ -166,4 +170,4 @@
companion object {
const val TILE_SPEC = "controls"
}
-}
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index f62b60b..4ebebea 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -35,7 +35,6 @@
import android.service.quicksettings.Tile;
import android.text.TextUtils;
import android.util.Log;
-import android.view.View;
import android.widget.Switch;
import androidx.annotation.Nullable;
@@ -47,6 +46,7 @@
import com.android.systemui.Prefs;
import com.android.systemui.animation.DialogCuj;
import com.android.systemui.animation.DialogTransitionAnimator;
+import com.android.systemui.animation.Expandable;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
@@ -147,12 +147,12 @@
}
@Override
- protected void handleClick(@Nullable View view) {
+ protected void handleClick(@Nullable Expandable expandable) {
// Zen is currently on
if (mState.value) {
mController.setZen(ZEN_MODE_OFF, null, TAG);
} else {
- enableZenMode(view);
+ enableZenMode(expandable);
}
}
@@ -162,7 +162,7 @@
mSettingZenDuration.setUserId(newUserId);
}
- private void enableZenMode(@Nullable View view) {
+ private void enableZenMode(@Nullable Expandable expandable) {
int zenDuration = mSettingZenDuration.getValue();
boolean showOnboarding = Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0) != 0
@@ -183,11 +183,17 @@
case Settings.Secure.ZEN_DURATION_PROMPT:
mUiHandler.post(() -> {
Dialog dialog = makeZenModeDialog();
- if (view != null) {
- mDialogTransitionAnimator.showFromView(dialog, view, new DialogCuj(
+ if (expandable != null) {
+ DialogTransitionAnimator.Controller controller =
+ expandable.dialogTransitionController(new DialogCuj(
InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN,
- INTERACTION_JANK_TAG),
- /* animateBackgroundBoundsChange= */ false);
+ INTERACTION_JANK_TAG));
+ if (controller != null) {
+ mDialogTransitionAnimator.show(dialog,
+ controller, /* animateBackgroundBoundsChange= */ false);
+ } else {
+ dialog.show();
+ }
} else {
dialog.show();
}
@@ -217,8 +223,8 @@
}
@Override
- protected void handleSecondaryClick(@Nullable View view) {
- handleLongClick(view);
+ protected void handleSecondaryClick(@Nullable Expandable expandable) {
+ handleLongClick(expandable);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DreamTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DreamTile.java
index 4f0a63b..0d3d980 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DreamTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DreamTile.java
@@ -32,12 +32,12 @@
import android.service.quicksettings.Tile;
import android.text.TextUtils;
import android.util.Log;
-import android.view.View;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
+import com.android.systemui.animation.Expandable;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
@@ -153,7 +153,7 @@
}
@Override
- protected void handleClick(@Nullable View view) {
+ protected void handleClick(@Nullable Expandable expandable) {
try {
if (mDreamManager.isDreaming()) {
mDreamManager.awaken();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
index f022981..848ff3c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
@@ -22,13 +22,13 @@
import android.os.Looper;
import android.provider.MediaStore;
import android.service.quicksettings.Tile;
-import android.view.View;
import android.widget.Switch;
import androidx.annotation.Nullable;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.systemui.animation.Expandable;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
@@ -99,7 +99,7 @@
}
@Override
- protected void handleClick(@Nullable View view) {
+ protected void handleClick(@Nullable Expandable expandable) {
if (ActivityManager.isUserAMonkey()) {
return;
}
@@ -114,8 +114,8 @@
}
@Override
- protected void handleLongClick(@Nullable View view) {
- handleClick(view);
+ protected void handleLongClick(@Nullable Expandable expandable) {
+ handleClick(expandable);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FontScalingTile.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/FontScalingTile.kt
index f5018a2..078698c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/FontScalingTile.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FontScalingTile.kt
@@ -19,12 +19,12 @@
import android.os.Handler
import android.os.Looper
import android.provider.Settings
-import android.view.View
import com.android.internal.jank.InteractionJankMonitor
import com.android.internal.logging.MetricsLogger
import com.android.systemui.accessibility.fontscaling.FontScalingDialogDelegate
import com.android.systemui.animation.DialogCuj
import com.android.systemui.animation.DialogTransitionAnimator
+import com.android.systemui.animation.Expandable
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.plugins.ActivityStarter
@@ -74,18 +74,23 @@
return QSTile.State()
}
- override fun handleClick(view: View?) {
+ override fun handleClick(expandable: Expandable?) {
// We animate from the touched view only if we are not on the keyguard
- val animateFromView: Boolean = view != null && !keyguardStateController.isShowing
+ val animateFromExpandable: Boolean =
+ expandable != null && !keyguardStateController.isShowing
val runnable = Runnable {
val dialog: SystemUIDialog = fontScalingDialogDelegateProvider.get().createDialog()
- if (animateFromView) {
- dialogTransitionAnimator.showFromView(
- dialog,
- view!!,
- DialogCuj(InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN, INTERACTION_JANK_TAG)
- )
+ if (animateFromExpandable) {
+ val controller =
+ expandable?.dialogTransitionController(
+ DialogCuj(
+ InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN,
+ INTERACTION_JANK_TAG
+ )
+ )
+ controller?.let { dialogTransitionAnimator.show(dialog, controller) }
+ ?: dialog.show()
} else {
dialog.show()
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HearingDevicesTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HearingDevicesTile.java
index 81a2026..183c1a4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HearingDevicesTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HearingDevicesTile.java
@@ -20,13 +20,13 @@
import android.os.Handler;
import android.os.Looper;
import android.provider.Settings;
-import android.view.View;
import androidx.annotation.Nullable;
import com.android.internal.logging.MetricsLogger;
import com.android.systemui.Flags;
import com.android.systemui.accessibility.hearingaid.HearingDevicesDialogManager;
+import com.android.systemui.animation.Expandable;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
@@ -72,8 +72,8 @@
}
@Override
- protected void handleClick(@Nullable View view) {
- mUiHandler.post(() -> mDialogManager.showDialog(view));
+ protected void handleClick(@Nullable Expandable expandable) {
+ mUiHandler.post(() -> mDialogManager.showDialog(expandable));
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
index 4d0404d..ea3993e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
@@ -25,7 +25,6 @@
import android.provider.Settings;
import android.service.quicksettings.Tile;
import android.util.Log;
-import android.view.View;
import android.widget.Switch;
import androidx.annotation.Nullable;
@@ -33,6 +32,7 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settingslib.wifi.WifiEnterpriseRestrictionUtils;
+import com.android.systemui.animation.Expandable;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
@@ -112,7 +112,7 @@
}
@Override
- protected void handleClick(@Nullable View view) {
+ protected void handleClick(@Nullable Expandable expandable) {
final boolean isEnabled = mState.value;
if (!isEnabled && mDataSaverController.isDataSaverEnabled()) {
return;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java
index 0f260e3..6d98da4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java
@@ -30,7 +30,6 @@
import android.text.Html;
import android.text.TextUtils;
import android.util.Log;
-import android.view.View;
import android.widget.Switch;
import androidx.annotation.Nullable;
@@ -41,6 +40,7 @@
import com.android.settingslib.graph.SignalDrawable;
import com.android.settingslib.mobile.TelephonyIcons;
import com.android.settingslib.net.DataUsageController;
+import com.android.systemui.animation.Expandable;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
@@ -124,10 +124,10 @@
}
@Override
- protected void handleClick(@Nullable View view) {
+ protected void handleClick(@Nullable Expandable expandable) {
mHandler.post(() -> mInternetDialogManager.create(true,
mAccessPointController.canConfigMobileData(),
- mAccessPointController.canConfigWifi(), view));
+ mAccessPointController.canConfigWifi(), expandable));
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTileNewImpl.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTileNewImpl.kt
index 357743b..932dec5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTileNewImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTileNewImpl.kt
@@ -20,9 +20,9 @@
import android.os.Handler
import android.os.Looper
import android.provider.Settings
-import android.view.View
import android.widget.Switch
import com.android.internal.logging.MetricsLogger
+import com.android.systemui.animation.Expandable
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.plugins.ActivityStarter
@@ -44,18 +44,18 @@
class InternetTileNewImpl
@Inject
constructor(
- host: QSHost,
- uiEventLogger: QsEventLogger,
- @Background backgroundLooper: Looper,
- @Main private val mainHandler: Handler,
- falsingManager: FalsingManager,
- metricsLogger: MetricsLogger,
- statusBarStateController: StatusBarStateController,
- activityStarter: ActivityStarter,
- qsLogger: QSLogger,
- viewModel: InternetTileViewModel,
- private val internetDialogManager: InternetDialogManager,
- private val accessPointController: AccessPointController,
+ host: QSHost,
+ uiEventLogger: QsEventLogger,
+ @Background backgroundLooper: Looper,
+ @Main private val mainHandler: Handler,
+ falsingManager: FalsingManager,
+ metricsLogger: MetricsLogger,
+ statusBarStateController: StatusBarStateController,
+ activityStarter: ActivityStarter,
+ qsLogger: QSLogger,
+ viewModel: InternetTileViewModel,
+ private val internetDialogManager: InternetDialogManager,
+ private val accessPointController: AccessPointController,
) :
QSTileImpl<QSTile.BooleanState>(
host,
@@ -84,13 +84,13 @@
return QSTile.BooleanState().also { it.forceExpandIcon = true }
}
- override fun handleClick(view: View?) {
+ override fun handleClick(expandable: Expandable?) {
mainHandler.post {
internetDialogManager.create(
aboveStatusBar = true,
accessPointController.canConfigMobileData(),
accessPointController.canConfigWifi(),
- view,
+ expandable,
)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
index b3f0d8b..cad5c0d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
@@ -22,13 +22,13 @@
import android.os.UserManager;
import android.provider.Settings;
import android.service.quicksettings.Tile;
-import android.view.View;
import android.widget.Switch;
import androidx.annotation.Nullable;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.systemui.animation.Expandable;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
@@ -92,7 +92,7 @@
}
@Override
- protected void handleClick(@Nullable View view) {
+ protected void handleClick(@Nullable Expandable expandable) {
if (mKeyguard.isMethodSecure() && mKeyguard.isShowing()) {
mActivityStarter.postQSRunnableDismissingKeyguard(() -> {
final boolean wasEnabled = mState.value;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java
index d650f73..136eea8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java
@@ -27,13 +27,13 @@
import android.os.Looper;
import android.provider.Settings;
import android.service.quicksettings.Tile;
-import android.view.View;
import android.widget.Switch;
import androidx.annotation.Nullable;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.systemui.animation.Expandable;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
@@ -119,7 +119,7 @@
}
@Override
- protected void handleClick(@Nullable View view) {
+ protected void handleClick(@Nullable Expandable expandable) {
if (getAdapter() == null) {
return;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
index a1ea46d..ac762de 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
@@ -28,7 +28,6 @@
import android.service.quicksettings.Tile;
import android.text.TextUtils;
import android.util.Log;
-import android.view.View;
import android.widget.Switch;
import androidx.annotation.Nullable;
@@ -36,6 +35,7 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.systemui.animation.Expandable;
import com.android.systemui.dagger.NightDisplayListenerModule;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
@@ -112,7 +112,7 @@
}
@Override
- protected void handleClick(@Nullable View view) {
+ protected void handleClick(@Nullable Expandable expandable) {
// Enroll in forced auto mode if eligible.
if ("1".equals(Settings.Global.getString(mContext.getContentResolver(),
Settings.Global.NIGHT_DISPLAY_FORCED_AUTO_MODE_AVAILABLE))
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/OneHandedModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/OneHandedModeTile.java
index b08e6a5..450c954 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/OneHandedModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/OneHandedModeTile.java
@@ -21,13 +21,13 @@
import android.os.Looper;
import android.provider.Settings;
import android.service.quicksettings.Tile;
-import android.view.View;
import android.widget.Switch;
import androidx.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
+import com.android.systemui.animation.Expandable;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
@@ -114,7 +114,7 @@
}
@Override
- protected void handleClick(@Nullable View view) {
+ protected void handleClick(@Nullable Expandable expandable) {
mSetting.setValue(mState.value ? 0 : 1);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/QRCodeScannerTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/QRCodeScannerTile.java
index de9a08e..9766fac 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/QRCodeScannerTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/QRCodeScannerTile.java
@@ -21,13 +21,13 @@
import android.os.Looper;
import android.service.quicksettings.Tile;
import android.util.Log;
-import android.view.View;
import androidx.annotation.Nullable;
import com.android.internal.jank.InteractionJankMonitor;
import com.android.internal.logging.MetricsLogger;
import com.android.systemui.animation.ActivityTransitionAnimator;
+import com.android.systemui.animation.Expandable;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
@@ -99,7 +99,7 @@
}
@Override
- protected void handleClick(@Nullable View view) {
+ protected void handleClick(@Nullable Expandable expandable) {
Intent intent = mQRCodeScannerController.getIntent();
if (intent == null) {
// This should never happen as the fact that we are handling clicks means that the
@@ -109,7 +109,7 @@
}
ActivityTransitionAnimator.Controller animationController =
- view == null ? null : ActivityTransitionAnimator.Controller.fromView(view,
+ expandable == null ? null : expandable.activityTransitionController(
InteractionJankMonitor.CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE);
mActivityStarter.startActivity(intent, true /* dismissShade */,
animationController, true /* showOverLockscreenWhenLocked */);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java
index e1b742e..76aa146 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java
@@ -35,7 +35,6 @@
import android.service.quickaccesswallet.WalletCard;
import android.service.quicksettings.Tile;
import android.util.Log;
-import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -44,6 +43,7 @@
import com.android.internal.jank.InteractionJankMonitor;
import com.android.internal.logging.MetricsLogger;
import com.android.systemui.animation.ActivityTransitionAnimator;
+import com.android.systemui.animation.Expandable;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
@@ -131,9 +131,9 @@
}
@Override
- protected void handleClick(@Nullable View view) {
+ protected void handleClick(@Nullable Expandable expandable) {
ActivityTransitionAnimator.Controller animationController =
- view == null ? null : ActivityTransitionAnimator.Controller.fromView(view,
+ expandable == null ? null : expandable.activityTransitionController(
InteractionJankMonitor.CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE);
mUiHandler.post(
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RecordIssueTile.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/RecordIssueTile.kt
index b418a17..9937ea4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RecordIssueTile.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RecordIssueTile.kt
@@ -24,7 +24,6 @@
import android.os.Looper
import android.service.quicksettings.Tile
import android.text.TextUtils
-import android.view.View
import android.widget.Switch
import androidx.annotation.VisibleForTesting
import com.android.internal.jank.InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN
@@ -32,6 +31,7 @@
import com.android.systemui.Flags.recordIssueQsTile
import com.android.systemui.animation.DialogCuj
import com.android.systemui.animation.DialogTransitionAnimator
+import com.android.systemui.animation.Expandable
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.plugins.ActivityStarter
@@ -113,11 +113,11 @@
}
@VisibleForTesting
- public override fun handleClick(view: View?) {
+ public override fun handleClick(expandable: Expandable?) {
if (issueRecordingState.isRecording) {
stopIssueRecordingService()
} else {
- mUiHandler.post { showPrompt(view) }
+ mUiHandler.post { showPrompt(expandable) }
}
}
@@ -143,7 +143,7 @@
)
.send(BroadcastOptions.makeBasic().apply { isInteractive = true }.toBundle())
- private fun showPrompt(view: View?) {
+ private fun showPrompt(expandable: Expandable?) {
val dialog: AlertDialog =
delegateFactory
.create {
@@ -156,12 +156,11 @@
ActivityStarter.OnDismissAction {
// We animate from the touched view only if we are not on the keyguard, given
// that if we are we will dismiss it which will also collapse the shade.
- if (view != null && !keyguardStateController.isShowing) {
- dialogTransitionAnimator.showFromView(
- dialog,
- view,
- DialogCuj(CUJ_SHADE_DIALOG_OPEN, TILE_SPEC)
- )
+ if (expandable != null && !keyguardStateController.isShowing) {
+ expandable
+ .dialogTransitionController(DialogCuj(CUJ_SHADE_DIALOG_OPEN, TILE_SPEC))
+ ?.let { dialogTransitionAnimator.show(dialog, it) }
+ ?: dialog.show()
} else {
dialog.show()
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ReduceBrightColorsTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ReduceBrightColorsTile.java
index 76ada10..3472352 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ReduceBrightColorsTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ReduceBrightColorsTile.java
@@ -23,13 +23,13 @@
import android.os.Looper;
import android.provider.Settings;
import android.service.quicksettings.Tile;
-import android.view.View;
import android.widget.Switch;
import androidx.annotation.Nullable;
import com.android.internal.R;
import com.android.internal.logging.MetricsLogger;
+import com.android.systemui.animation.Expandable;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
@@ -97,7 +97,7 @@
}
@Override
- protected void handleClick(@Nullable View view) {
+ protected void handleClick(@Nullable Expandable expandable) {
mReduceBrightColorsController.setReduceBrightColorsActivated(!mState.value);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
index f1d8f9f..35e43b6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
@@ -29,13 +29,13 @@
import android.provider.Settings;
import android.provider.Settings.Secure;
import android.service.quicksettings.Tile;
-import android.view.View;
import android.widget.Switch;
import androidx.annotation.Nullable;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.systemui.animation.Expandable;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
@@ -131,7 +131,7 @@
}
@Override
- protected void handleClick(@Nullable View view) {
+ protected void handleClick(@Nullable Expandable expandable) {
final boolean newState = !mState.value;
mController.setRotationLocked(!newState, /* caller= */ "RotationLockTile#handleClick");
refreshState(newState);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java
index 1a90d43..4715230 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java
@@ -23,7 +23,6 @@
import android.service.quicksettings.Tile;
import android.text.TextUtils;
import android.util.Log;
-import android.view.View;
import android.widget.Switch;
import androidx.annotation.Nullable;
@@ -32,6 +31,7 @@
import com.android.internal.logging.MetricsLogger;
import com.android.systemui.animation.DialogCuj;
import com.android.systemui.animation.DialogTransitionAnimator;
+import com.android.systemui.animation.Expandable;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.flags.FeatureFlags;
@@ -118,13 +118,13 @@
}
@Override
- protected void handleClick(@Nullable View view) {
+ protected void handleClick(@Nullable Expandable expandable) {
if (mController.isStarting()) {
cancelCountdown();
} else if (mController.isRecording()) {
stopRecording();
} else {
- mUiHandler.post(() -> showPrompt(view));
+ mUiHandler.post(() -> showPrompt(expandable));
}
refreshState();
}
@@ -174,10 +174,11 @@
return mContext.getString(R.string.quick_settings_screen_record_label);
}
- private void showPrompt(@Nullable View view) {
+ private void showPrompt(@Nullable Expandable expandable) {
// We animate from the touched view only if we are not on the keyguard, given that if we
// are we will dismiss it which will also collapse the shade.
- boolean shouldAnimateFromView = view != null && !mKeyguardStateController.isShowing();
+ boolean shouldAnimateFromExpandable =
+ expandable != null && !mKeyguardStateController.isShowing();
// Create the recording dialog that will collapse the shade only if we start the recording.
Runnable onStartRecordingClicked = () -> {
@@ -192,10 +193,17 @@
mDialogTransitionAnimator, mActivityStarter, onStartRecordingClicked);
ActivityStarter.OnDismissAction dismissAction = () -> {
- if (shouldAnimateFromView) {
- mDialogTransitionAnimator.showFromView(dialog, view, new DialogCuj(
- InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN, INTERACTION_JANK_TAG),
- /* animateBackgroundBoundsChange= */ true);
+ if (shouldAnimateFromExpandable) {
+ DialogTransitionAnimator.Controller controller =
+ expandable.dialogTransitionController(new DialogCuj(
+ InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN,
+ INTERACTION_JANK_TAG));
+ if (controller != null) {
+ mDialogTransitionAnimator.show(dialog,
+ controller, /* animateBackgroundBoundsChange= */ true);
+ } else {
+ dialog.show();
+ }
} else {
dialog.show();
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java
index 3eeb2a3..036ce08 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java
@@ -26,13 +26,13 @@
import android.safetycenter.SafetyCenterManager;
import android.service.quicksettings.Tile;
import android.text.TextUtils;
-import android.view.View;
import android.widget.Switch;
import androidx.annotation.DrawableRes;
import androidx.annotation.Nullable;
import com.android.internal.logging.MetricsLogger;
+import com.android.systemui.animation.Expandable;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
@@ -100,7 +100,7 @@
}
@Override
- protected void handleClick(@Nullable View view) {
+ protected void handleClick(@Nullable Expandable expandable) {
boolean blocked = mSensorPrivacyController.isSensorBlocked(getSensorId());
if (mSensorPrivacyController.requiresAuthentication()
&& mKeyguard.isMethodSecure()
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java
index d92873ada..bec6581 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java
@@ -24,13 +24,13 @@
import android.provider.Settings;
import android.service.quicksettings.Tile;
import android.text.TextUtils;
-import android.view.View;
import android.widget.Switch;
import androidx.annotation.Nullable;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
+import com.android.systemui.animation.Expandable;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
@@ -107,7 +107,7 @@
}
@Override
- protected void handleClick(@Nullable View view) {
+ protected void handleClick(@Nullable Expandable expandable) {
if (getState().state == Tile.STATE_UNAVAILABLE) {
return;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
index abc4812..d9546ec 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
@@ -24,7 +24,6 @@
import android.os.Looper;
import android.provider.Settings;
import android.service.quicksettings.Tile;
-import android.view.View;
import android.widget.Switch;
import androidx.annotation.MainThread;
@@ -32,6 +31,7 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.systemui.animation.Expandable;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
@@ -88,7 +88,7 @@
}
@Override
- public void handleClick(@Nullable View view) {
+ public void handleClick(@Nullable Expandable expandable) {
mProfileController.setWorkModeEnabled(!mState.value);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/base/actions/QSTileIntentUserInputHandler.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/base/actions/QSTileIntentUserInputHandler.kt
index 7192f58..2d3120a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/base/actions/QSTileIntentUserInputHandler.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/base/actions/QSTileIntentUserInputHandler.kt
@@ -20,9 +20,9 @@
import android.content.Intent
import android.content.pm.PackageManager
import android.os.UserHandle
-import android.view.View
import com.android.internal.jank.InteractionJankMonitor
import com.android.systemui.animation.ActivityTransitionAnimator
+import com.android.systemui.animation.Expandable
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.plugins.ActivityStarter
import javax.inject.Inject
@@ -33,11 +33,11 @@
*/
interface QSTileIntentUserInputHandler {
- fun handle(view: View?, intent: Intent)
+ fun handle(expandable: Expandable?, intent: Intent)
/** @param requestLaunchingDefaultActivity used in case !pendingIndent.isActivity */
fun handle(
- view: View?,
+ expandable: Expandable?,
pendingIntent: PendingIntent,
requestLaunchingDefaultActivity: Boolean = false
)
@@ -52,31 +52,25 @@
private val userHandle: UserHandle,
) : QSTileIntentUserInputHandler {
- override fun handle(view: View?, intent: Intent) {
+ override fun handle(expandable: Expandable?, intent: Intent) {
val animationController: ActivityTransitionAnimator.Controller? =
- view?.let {
- ActivityTransitionAnimator.Controller.fromView(
- it,
- InteractionJankMonitor.CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE,
- )
- }
+ expandable?.activityTransitionController(
+ InteractionJankMonitor.CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE
+ )
activityStarter.postStartActivityDismissingKeyguard(intent, 0, animationController)
}
// TODO(b/249804373): make sure to allow showing activities over the lockscreen. See b/292112939
override fun handle(
- view: View?,
+ expandable: Expandable?,
pendingIntent: PendingIntent,
requestLaunchingDefaultActivity: Boolean
) {
if (pendingIntent.isActivity) {
val animationController: ActivityTransitionAnimator.Controller? =
- view?.let {
- ActivityTransitionAnimator.Controller.fromView(
- it,
- InteractionJankMonitor.CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE,
- )
- }
+ expandable?.activityTransitionController(
+ InteractionJankMonitor.CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE
+ )
activityStarter.postStartActivityDismissingKeyguard(pendingIntent, animationController)
} else if (requestLaunchingDefaultActivity) {
val intent =
@@ -97,7 +91,7 @@
?.let { resolved ->
intent.setPackage(null)
intent.setComponent(resolved.activityInfo.componentName)
- handle(view, intent)
+ handle(expandable, intent)
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogManager.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogManager.kt
index 5aef950..246fe38 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogManager.kt
@@ -16,10 +16,10 @@
package com.android.systemui.qs.tiles.dialog
import android.util.Log
-import android.view.View
import com.android.internal.jank.InteractionJankMonitor
import com.android.systemui.animation.DialogCuj
import com.android.systemui.animation.DialogTransitionAnimator
+import com.android.systemui.animation.Expandable
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.statusbar.phone.SystemUIDialog
@@ -47,14 +47,14 @@
}
/**
- * Creates a [InternetDialogDelegate]. The dialog will be animated from [view] if it is not
- * null.
+ * Creates a [InternetDialogDelegate]. The dialog will be animated from [expandable] if it is
+ * not null.
*/
fun create(
aboveStatusBar: Boolean,
canConfigMobileData: Boolean,
canConfigWifi: Boolean,
- view: View?
+ expandable: Expandable?
) {
if (dialog != null) {
if (DEBUG) {
@@ -67,20 +67,18 @@
dialogFactory
.create(aboveStatusBar, canConfigMobileData, canConfigWifi, coroutineScope)
.createDialog()
- if (view != null) {
- dialogTransitionAnimator.showFromView(
- dialog!!,
- view,
- animateBackgroundBoundsChange = true,
- cuj =
- DialogCuj(
- InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN,
- INTERACTION_JANK_TAG
- )
+ val controller =
+ expandable?.dialogTransitionController(
+ DialogCuj(InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN, INTERACTION_JANK_TAG)
)
- } else {
- dialog!!.show()
+ controller?.let {
+ dialogTransitionAnimator.show(
+ dialog!!,
+ controller,
+ animateBackgroundBoundsChange = true
+ )
}
+ ?: dialog?.show()
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/airplane/domain/interactor/AirplaneModeTileUserActionInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/airplane/domain/interactor/AirplaneModeTileUserActionInteractor.kt
index 9e13a56..bf0f8f6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/airplane/domain/interactor/AirplaneModeTileUserActionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/airplane/domain/interactor/AirplaneModeTileUserActionInteractor.kt
@@ -45,7 +45,7 @@
}
AirplaneModeInteractor.SetResult.BLOCKED_BY_ECM -> {
qsTileIntentUserActionHandler.handle(
- action.view,
+ action.expandable,
Intent(TelephonyManager.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS),
)
}
@@ -53,7 +53,7 @@
}
is QSTileUserAction.LongClick -> {
qsTileIntentUserActionHandler.handle(
- action.view,
+ action.expandable,
Intent(Settings.ACTION_AIRPLANE_MODE_SETTINGS)
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/alarm/domain/interactor/AlarmTileUserActionInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/alarm/domain/interactor/AlarmTileUserActionInteractor.kt
index 0ad520b..14fc57c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/alarm/domain/interactor/AlarmTileUserActionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/alarm/domain/interactor/AlarmTileUserActionInteractor.kt
@@ -40,9 +40,12 @@
data.alarmClockInfo.showIntent != null
) {
val pendingIndent = data.alarmClockInfo.showIntent
- inputHandler.handle(action.view, pendingIndent, true)
+ inputHandler.handle(action.expandable, pendingIndent, true)
} else {
- inputHandler.handle(action.view, Intent(AlarmClock.ACTION_SHOW_ALARMS))
+ inputHandler.handle(
+ action.expandable,
+ Intent(AlarmClock.ACTION_SHOW_ALARMS)
+ )
}
}
is QSTileUserAction.LongClick -> {}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/battery/domain/interactor/BatterySaverTileUserActionInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/battery/domain/interactor/BatterySaverTileUserActionInteractor.kt
index 1e4eb38..d4b4fe0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/battery/domain/interactor/BatterySaverTileUserActionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/battery/domain/interactor/BatterySaverTileUserActionInteractor.kt
@@ -39,12 +39,12 @@
when (action) {
is QSTileUserAction.Click -> {
if (!data.isPluggedIn) {
- batteryController.setPowerSaveMode(!data.isPowerSaving, action.view)
+ batteryController.setPowerSaveMode(!data.isPowerSaving, action.expandable)
}
}
is QSTileUserAction.LongClick -> {
qsTileIntentUserActionHandler.handle(
- action.view,
+ action.expandable,
Intent(Settings.ACTION_BATTERY_SAVER_SETTINGS)
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/colorcorrection/domain/interactor/ColorCorrectionUserActionInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/colorcorrection/domain/interactor/ColorCorrectionUserActionInteractor.kt
index d183802..534bd73 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/colorcorrection/domain/interactor/ColorCorrectionUserActionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/colorcorrection/domain/interactor/ColorCorrectionUserActionInteractor.kt
@@ -45,7 +45,7 @@
}
is QSTileUserAction.LongClick -> {
qsTileIntentUserActionHandler.handle(
- action.view,
+ action.expandable,
Intent(Settings.ACTION_COLOR_CORRECTION_SETTINGS)
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/domain/interactor/CustomTileUserActionInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/domain/interactor/CustomTileUserActionInteractor.kt
index a16ac36..9bdf631 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/domain/interactor/CustomTileUserActionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/domain/interactor/CustomTileUserActionInteractor.kt
@@ -29,9 +29,9 @@
import android.provider.Settings
import android.service.quicksettings.TileService
import android.view.IWindowManager
-import android.view.View
import android.view.WindowManager
import androidx.annotation.GuardedBy
+import com.android.systemui.animation.Expandable
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.qs.pipeline.shared.TileSpec
import com.android.systemui.qs.tiles.base.actions.QSTileIntentUserInputHandler
@@ -65,20 +65,21 @@
@GuardedBy("token") private var isTokenGranted: Boolean = false
@GuardedBy("token") private var isShowingDialog: Boolean = false
- private val lastClickedView: AtomicReference<View> = AtomicReference<View>()
+ private val lastClickedExpandable: AtomicReference<Expandable> = AtomicReference<Expandable>()
override suspend fun handleInput(input: QSTileInput<CustomTileDataModel>) =
with(input) {
when (action) {
- is QSTileUserAction.Click -> click(action.view, data.tile.activityLaunchForClick)
+ is QSTileUserAction.Click ->
+ click(action.expandable, data.tile.activityLaunchForClick)
is QSTileUserAction.LongClick ->
- longClick(user, action.view, data.componentName, data.tile.state)
+ longClick(user, action.expandable, data.componentName, data.tile.state)
}
qsTileLogger.logCustomTileUserActionDelivered(tileSpec)
}
private suspend fun click(
- view: View?,
+ expandable: Expandable?,
activityLaunchForClick: PendingIntent?,
) {
grantToken()
@@ -86,10 +87,10 @@
// Bind active tile to deliver user action
serviceInteractor.bindOnClick()
if (activityLaunchForClick == null) {
- lastClickedView.set(view)
+ lastClickedExpandable.set(expandable)
serviceInteractor.onClick(token)
} else {
- qsTileIntentUserInputHandler.handle(view, activityLaunchForClick)
+ qsTileIntentUserInputHandler.handle(expandable, activityLaunchForClick)
}
} catch (e: RemoteException) {
qsTileLogger.logError(tileSpec, "Failed to deliver click", e)
@@ -117,10 +118,10 @@
if (!isTokenGranted) {
return
}
- qsTileIntentUserInputHandler.handle(lastClickedView.getAndSet(null), pendingIntent)
+ qsTileIntentUserInputHandler.handle(lastClickedExpandable.getAndSet(null), pendingIntent)
}
- fun clearLastClickedView() = lastClickedView.set(null)
+ fun clearLastClickedView() = lastClickedExpandable.set(null)
private fun grantToken() {
synchronized(token) {
@@ -142,7 +143,7 @@
private suspend fun longClick(
user: UserHandle,
- view: View?,
+ expandable: Expandable?,
componentName: ComponentName,
state: Int
) {
@@ -159,14 +160,14 @@
}
if (resolvedIntent == null) {
qsTileIntentUserInputHandler.handle(
- view,
+ expandable,
Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
.setData(
Uri.fromParts(IntentFilter.SCHEME_PACKAGE, componentName.packageName, null)
)
)
} else {
- qsTileIntentUserInputHandler.handle(view, resolvedIntent)
+ qsTileIntentUserInputHandler.handle(expandable, resolvedIntent)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/fontscaling/domain/interactor/FontScalingTileUserActionInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/fontscaling/domain/interactor/FontScalingTileUserActionInteractor.kt
index db8b1a5..d308ec8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/fontscaling/domain/interactor/FontScalingTileUserActionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/fontscaling/domain/interactor/FontScalingTileUserActionInteractor.kt
@@ -52,21 +52,22 @@
with(input) {
when (action) {
is QSTileUserAction.Click -> {
- // We animate from the touched view only if we are not on the keyguard
- val animateFromView: Boolean =
- action.view != null && !keyguardStateController.isShowing
+ // We animate from the touched expandable only if we are not on the keyguard
+ val animateFromExpandable: Boolean =
+ action.expandable != null && !keyguardStateController.isShowing
val runnable = Runnable {
val dialog: SystemUIDialog =
fontScalingDialogDelegateProvider.get().createDialog()
- if (animateFromView) {
- dialogTransitionAnimator.showFromView(
- dialog,
- action.view!!,
- DialogCuj(
- InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN,
- INTERACTION_JANK_TAG
+ if (animateFromExpandable) {
+ action.expandable
+ ?.dialogTransitionController(
+ DialogCuj(
+ InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN,
+ INTERACTION_JANK_TAG
+ )
)
- )
+ ?.let { dialogTransitionAnimator.show(dialog, it) }
+ ?: dialog.show()
} else {
dialog.show()
}
@@ -84,7 +85,7 @@
}
is QSTileUserAction.LongClick -> {
qsTileIntentUserActionHandler.handle(
- action.view,
+ action.expandable,
Intent(Settings.ACTION_TEXT_READING_SETTINGS)
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileUserActionInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileUserActionInteractor.kt
index 2620cd5..c0b089d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileUserActionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileUserActionInteractor.kt
@@ -49,13 +49,13 @@
aboveStatusBar = true,
accessPointController.canConfigMobileData(),
accessPointController.canConfigWifi(),
- action.view,
+ action.expandable,
)
}
}
is QSTileUserAction.LongClick -> {
qsTileIntentUserActionHandler.handle(
- action.view,
+ action.expandable,
Intent(Settings.ACTION_WIFI_SETTINGS)
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/inversion/domain/interactor/ColorInversionUserActionInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/inversion/domain/interactor/ColorInversionUserActionInteractor.kt
index 43b58c8..d643273 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/inversion/domain/interactor/ColorInversionUserActionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/inversion/domain/interactor/ColorInversionUserActionInteractor.kt
@@ -45,7 +45,7 @@
}
is QSTileUserAction.LongClick -> {
qsTileIntentUserActionHandler.handle(
- action.view,
+ action.expandable,
Intent(Settings.ACTION_COLOR_INVERSION_SETTINGS)
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/location/domain/interactor/LocationTileUserActionInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/location/domain/interactor/LocationTileUserActionInteractor.kt
index 66705ea..77404aa 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/location/domain/interactor/LocationTileUserActionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/location/domain/interactor/LocationTileUserActionInteractor.kt
@@ -64,7 +64,7 @@
}
is QSTileUserAction.LongClick -> {
qsTileIntentUserActionHandler.handle(
- action.view,
+ action.expandable,
Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/onehanded/domain/OneHandedModeTileDataInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/onehanded/domain/OneHandedModeTileDataInteractor.kt
new file mode 100644
index 0000000..8c0fd2c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/onehanded/domain/OneHandedModeTileDataInteractor.kt
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.onehanded.domain
+
+import android.os.UserHandle
+import com.android.systemui.accessibility.data.repository.OneHandedModeRepository
+import com.android.systemui.qs.tiles.base.interactor.DataUpdateTrigger
+import com.android.systemui.qs.tiles.base.interactor.QSTileDataInteractor
+import com.android.systemui.qs.tiles.impl.onehanded.domain.model.OneHandedModeTileModel
+import com.android.wm.shell.onehanded.OneHanded
+import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.map
+
+/** Observes one handed mode state changes providing the [OneHandedModeTileModel]. */
+class OneHandedModeTileDataInteractor
+@Inject
+constructor(
+ private val oneHandedModeRepository: OneHandedModeRepository,
+) : QSTileDataInteractor<OneHandedModeTileModel> {
+
+ override fun tileData(
+ user: UserHandle,
+ triggers: Flow<DataUpdateTrigger>
+ ): Flow<OneHandedModeTileModel> {
+ return oneHandedModeRepository.isEnabled(user).map { OneHandedModeTileModel(it) }
+ }
+ override fun availability(user: UserHandle): Flow<Boolean> =
+ flowOf(OneHanded.sIsSupportOneHandedMode)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/onehanded/domain/OneHandedModeTileUserActionInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/onehanded/domain/OneHandedModeTileUserActionInteractor.kt
new file mode 100644
index 0000000..5cb0e18
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/onehanded/domain/OneHandedModeTileUserActionInteractor.kt
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.onehanded.domain
+
+import android.content.Intent
+import android.provider.Settings
+import com.android.systemui.accessibility.data.repository.OneHandedModeRepository
+import com.android.systemui.qs.tiles.base.actions.QSTileIntentUserInputHandler
+import com.android.systemui.qs.tiles.base.interactor.QSTileInput
+import com.android.systemui.qs.tiles.base.interactor.QSTileUserActionInteractor
+import com.android.systemui.qs.tiles.impl.onehanded.domain.model.OneHandedModeTileModel
+import com.android.systemui.qs.tiles.viewmodel.QSTileUserAction
+import javax.inject.Inject
+
+/** Handles one handed mode tile clicks. */
+class OneHandedModeTileUserActionInteractor
+@Inject
+constructor(
+ private val oneHandedModeRepository: OneHandedModeRepository,
+ private val qsTileIntentUserActionHandler: QSTileIntentUserInputHandler,
+) : QSTileUserActionInteractor<OneHandedModeTileModel> {
+
+ override suspend fun handleInput(input: QSTileInput<OneHandedModeTileModel>): Unit =
+ with(input) {
+ when (action) {
+ is QSTileUserAction.Click -> {
+ oneHandedModeRepository.setIsEnabled(
+ !data.isEnabled,
+ user,
+ )
+ }
+ is QSTileUserAction.LongClick -> {
+ qsTileIntentUserActionHandler.handle(
+ action.expandable,
+ Intent(Settings.ACTION_ONE_HANDED_SETTINGS)
+ )
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/shared/model/GridLayoutTypeKey.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/onehanded/domain/model/OneHandedModeTileModel.kt
similarity index 64%
rename from packages/SystemUI/src/com/android/systemui/qs/panels/shared/model/GridLayoutTypeKey.kt
rename to packages/SystemUI/src/com/android/systemui/qs/tiles/impl/onehanded/domain/model/OneHandedModeTileModel.kt
index 0dbaaba..7cebdfe 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/shared/model/GridLayoutTypeKey.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/onehanded/domain/model/OneHandedModeTileModel.kt
@@ -14,15 +14,11 @@
* limitations under the License.
*/
-package com.android.systemui.qs.panels.shared.model
-
-import dagger.MapKey
-import kotlin.reflect.KClass
+package com.android.systemui.qs.tiles.impl.onehanded.domain.model
/**
- * Dagger map key to associate a [GridLayoutType] with its
- * [com.android.systemui.qs.panels.ui.compose.GridLayout].
+ * One handed mode tile model.
+ *
+ * @param isEnabled is true when one handed mode is enabled;
*/
-@Retention(AnnotationRetention.RUNTIME)
-@MapKey
-annotation class GridLayoutTypeKey(val value: KClass<out GridLayoutType>)
+@JvmInline value class OneHandedModeTileModel(val isEnabled: Boolean)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/onehanded/ui/OneHandedModeTileMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/onehanded/ui/OneHandedModeTileMapper.kt
new file mode 100644
index 0000000..9166ed8
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/onehanded/ui/OneHandedModeTileMapper.kt
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.onehanded.ui
+
+import android.content.res.Resources
+import com.android.systemui.common.shared.model.Icon
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.qs.tiles.base.interactor.QSTileDataToStateMapper
+import com.android.systemui.qs.tiles.impl.onehanded.domain.model.OneHandedModeTileModel
+import com.android.systemui.qs.tiles.viewmodel.QSTileConfig
+import com.android.systemui.qs.tiles.viewmodel.QSTileState
+import com.android.systemui.res.R
+import javax.inject.Inject
+
+/** Maps [OneHandedModeTileModel] to [QSTileState]. */
+class OneHandedModeTileMapper
+@Inject
+constructor(
+ @Main private val resources: Resources,
+ private val theme: Resources.Theme,
+) : QSTileDataToStateMapper<OneHandedModeTileModel> {
+
+ override fun map(config: QSTileConfig, data: OneHandedModeTileModel): QSTileState =
+ QSTileState.build(resources, theme, config.uiConfig) {
+ val subtitleArray = resources.getStringArray(R.array.tile_states_onehanded)
+ label = resources.getString(R.string.quick_settings_onehanded_label)
+ icon = {
+ Icon.Loaded(
+ resources.getDrawable(
+ com.android.internal.R.drawable.ic_qs_one_handed_mode,
+ theme
+ ),
+ null
+ )
+ }
+ if (data.isEnabled) {
+ activationState = QSTileState.ActivationState.ACTIVE
+ secondaryLabel = subtitleArray[2]
+ } else {
+ activationState = QSTileState.ActivationState.INACTIVE
+ secondaryLabel = subtitleArray[1]
+ }
+ sideViewIcon = QSTileState.SideViewIcon.None
+ contentDescription = label
+ supportedActions =
+ setOf(QSTileState.UserAction.CLICK, QSTileState.UserAction.LONG_CLICK)
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/reducebrightness/domain/interactor/ReduceBrightColorsTileUserActionInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/reducebrightness/domain/interactor/ReduceBrightColorsTileUserActionInteractor.kt
index 762f863..14dbe0e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/reducebrightness/domain/interactor/ReduceBrightColorsTileUserActionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/reducebrightness/domain/interactor/ReduceBrightColorsTileUserActionInteractor.kt
@@ -44,7 +44,7 @@
}
is QSTileUserAction.LongClick -> {
qsTileIntentUserActionHandler.handle(
- action.view,
+ action.expandable,
Intent(Settings.ACTION_REDUCE_BRIGHT_COLORS_SETTINGS)
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/rotation/domain/interactor/RotationLockTileUserActionInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/rotation/domain/interactor/RotationLockTileUserActionInteractor.kt
index 8530926..34385ea 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/rotation/domain/interactor/RotationLockTileUserActionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/rotation/domain/interactor/RotationLockTileUserActionInteractor.kt
@@ -42,7 +42,7 @@
}
is QSTileUserAction.LongClick -> {
qsTileIntentUserActionHandler.handle(
- action.view,
+ action.expandable,
Intent(Settings.ACTION_AUTO_ROTATE_SETTINGS)
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/saver/domain/interactor/DataSaverTileUserActionInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/saver/domain/interactor/DataSaverTileUserActionInteractor.kt
index 861faf5..a5dc66c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/saver/domain/interactor/DataSaverTileUserActionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/saver/domain/interactor/DataSaverTileUserActionInteractor.kt
@@ -75,34 +75,32 @@
// must be created and shown on the main thread, so we post it to the UI
// handler
withContext(coroutineContext) {
- val dialogContext = action.view?.context ?: context
val dialogDelegate =
DataSaverDialogDelegate(
systemUIDialogFactory,
- dialogContext,
+ context,
backgroundContext,
dataSaverController,
sharedPreferences
)
- val dialog = systemUIDialogFactory.create(dialogDelegate, dialogContext)
+ val dialog = systemUIDialogFactory.create(dialogDelegate, context)
- if (action.view != null) {
- dialogTransitionAnimator.showFromView(
- dialog,
- action.view!!,
+ action.expandable
+ ?.dialogTransitionController(
DialogCuj(
InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN,
INTERACTION_JANK_TAG
)
)
- } else {
- dialog.show()
- }
+ ?.let { controller ->
+ dialogTransitionAnimator.show(dialog, controller)
+ }
+ ?: dialog.show()
}
}
is QSTileUserAction.LongClick -> {
qsTileIntentUserActionHandler.handle(
- action.view,
+ action.expandable,
Intent(Settings.ACTION_DATA_SAVER_SETTINGS)
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/screenrecord/domain/interactor/ScreenRecordTileUserActionInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/screenrecord/domain/interactor/ScreenRecordTileUserActionInteractor.kt
index d2bd09f..79766d6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/screenrecord/domain/interactor/ScreenRecordTileUserActionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/screenrecord/domain/interactor/ScreenRecordTileUserActionInteractor.kt
@@ -18,10 +18,10 @@
import android.content.Context
import android.util.Log
-import android.view.View
import com.android.internal.jank.InteractionJankMonitor
import com.android.systemui.animation.DialogCuj
import com.android.systemui.animation.DialogTransitionAnimator
+import com.android.systemui.animation.Expandable
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
@@ -68,14 +68,16 @@
is ScreenRecordTileModel.Recording ->
withContext(backgroundContext) { recordingController.stopRecording() }
is ScreenRecordTileModel.DoingNothing ->
- withContext(mainContext) { showPrompt(action.view, user.identifier) }
+ withContext(mainContext) {
+ showPrompt(action.expandable, user.identifier)
+ }
}
}
is QSTileUserAction.LongClick -> {} // no-op
}
}
- private fun showPrompt(view: View?, userId: Int) {
+ private fun showPrompt(expandable: Expandable?, userId: Int) {
// Create the recording dialog that will collapse the shade only if we start the recording.
val onStartRecordingClicked = Runnable {
// We dismiss the shade. Since starting the recording will also dismiss the dialog, we
@@ -99,21 +101,29 @@
return
}
- // We animate from the touched view only if we are not on the keyguard, given that if we
+ // We animate from the touched expandable only if we are not on the keyguard, given that if
+ // we
// are we will dismiss it which will also collapse the shade.
- val shouldAnimateFromView = view != null && !keyguardInteractor.isKeyguardShowing()
+ val shouldAnimateFromExpandable =
+ expandable != null && !keyguardInteractor.isKeyguardShowing()
val dismissAction =
ActivityStarter.OnDismissAction {
- if (shouldAnimateFromView) {
- dialogTransitionAnimator.showFromView(
- dialog,
- view!!,
- DialogCuj(
- InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN,
- INTERACTION_JANK_TAG
- ),
- animateBackgroundBoundsChange = true
- )
+ if (shouldAnimateFromExpandable) {
+ val controller =
+ expandable?.dialogTransitionController(
+ DialogCuj(
+ InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN,
+ INTERACTION_JANK_TAG
+ )
+ )
+ controller?.let {
+ dialogTransitionAnimator.show(
+ dialog,
+ controller,
+ animateBackgroundBoundsChange = true,
+ )
+ }
+ ?: dialog.show()
} else {
dialog.show()
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/sensorprivacy/domain/SensorPrivacyToggleTileUserActionInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/sensorprivacy/domain/SensorPrivacyToggleTileUserActionInteractor.kt
index 9711cb8..f22a426 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/sensorprivacy/domain/SensorPrivacyToggleTileUserActionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/sensorprivacy/domain/SensorPrivacyToggleTileUserActionInteractor.kt
@@ -80,7 +80,7 @@
}
)
}
- qsTileIntentUserActionHandler.handle(action.view, longClickIntent)
+ qsTileIntentUserActionHandler.handle(action.expandable, longClickIntent)
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/uimodenight/domain/interactor/UiModeNightTileUserActionInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/uimodenight/domain/interactor/UiModeNightTileUserActionInteractor.kt
index 00d7a62..f8dd1730 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/uimodenight/domain/interactor/UiModeNightTileUserActionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/uimodenight/domain/interactor/UiModeNightTileUserActionInteractor.kt
@@ -50,7 +50,7 @@
}
is QSTileUserAction.LongClick -> {
qsTileIntentUserActionHandler.handle(
- action.view,
+ action.expandable,
Intent(Settings.ACTION_DARK_THEME_SETTINGS)
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/work/domain/interactor/WorkModeTileUserActionInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/work/domain/interactor/WorkModeTileUserActionInteractor.kt
index f765f8b..031e4d9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/work/domain/interactor/WorkModeTileUserActionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/work/domain/interactor/WorkModeTileUserActionInteractor.kt
@@ -44,7 +44,7 @@
is QSTileUserAction.LongClick -> {
if (data is WorkModeTileModel.HasActiveProfile) {
qsTileIntentUserActionHandler.handle(
- action.view,
+ action.expandable,
Intent(Settings.ACTION_MANAGED_PROFILE_SETTINGS)
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileUserAction.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileUserAction.kt
index a145042..acb2936 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileUserAction.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileUserAction.kt
@@ -16,12 +16,12 @@
package com.android.systemui.qs.tiles.viewmodel
-import android.view.View
+import com.android.systemui.animation.Expandable
sealed interface QSTileUserAction {
- val view: View?
+ val expandable: Expandable?
- class Click(override val view: View?) : QSTileUserAction
- class LongClick(override val view: View?) : QSTileUserAction
+ class Click(override val expandable: Expandable?) : QSTileUserAction
+ class LongClick(override val expandable: Expandable?) : QSTileUserAction
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelAdapter.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelAdapter.kt
index 5a389f3..b88c1e5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelAdapter.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelAdapter.kt
@@ -19,10 +19,10 @@
import android.content.Context
import android.os.UserHandle
import android.util.Log
-import android.view.View
import androidx.annotation.GuardedBy
import com.android.internal.logging.InstanceId
import com.android.systemui.Dumpable
+import com.android.systemui.animation.Expandable
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.plugins.qs.QSTile
@@ -126,21 +126,21 @@
synchronized(callbacks) { callbacks.clear() }
}
- override fun click(view: View?) {
+ override fun click(expandable: Expandable?) {
if (isActionSupported(QSTileState.UserAction.CLICK)) {
- qsTileViewModel.onActionPerformed(QSTileUserAction.Click(view))
+ qsTileViewModel.onActionPerformed(QSTileUserAction.Click(expandable))
}
}
- override fun secondaryClick(view: View?) {
+ override fun secondaryClick(expandable: Expandable?) {
if (isActionSupported(QSTileState.UserAction.CLICK)) {
- qsTileViewModel.onActionPerformed(QSTileUserAction.Click(view))
+ qsTileViewModel.onActionPerformed(QSTileUserAction.Click(expandable))
}
}
- override fun longClick(view: View?) {
+ override fun longClick(expandable: Expandable?) {
if (isActionSupported(QSTileState.UserAction.LONG_CLICK)) {
- qsTileViewModel.onActionPerformed(QSTileUserAction.LongClick(view))
+ qsTileViewModel.onActionPerformed(QSTileUserAction.LongClick(expandable))
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/ui/adapter/QSSceneAdapter.kt b/packages/SystemUI/src/com/android/systemui/qs/ui/adapter/QSSceneAdapter.kt
index 3d86e3c..63acbb0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/ui/adapter/QSSceneAdapter.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/ui/adapter/QSSceneAdapter.kt
@@ -49,21 +49,44 @@
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.stateIn
+import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
// TODO(307945185) Split View concerns into a ViewBinder
/** Adapter to use between Scene system and [QSImpl] */
interface QSSceneAdapter {
- /** Whether [QSImpl] is currently customizing */
+
+ /**
+ * Whether we are currently customizing or entering the customizer.
+ *
+ * @see CustomizerState.isCustomizing
+ */
val isCustomizing: StateFlow<Boolean>
/**
+ * Whether the customizer is showing. This includes animating into and out of it.
+ *
+ * @see CustomizerState.isShowing
+ */
+ val isCustomizerShowing: StateFlow<Boolean>
+
+ /**
+ * The duration of the current animation in/out of customizer. If not in an animating state,
+ * this duration is 0 (to match show/hide immediately).
+ *
+ * @see CustomizerState.Animating.animationDuration
+ */
+ val customizerAnimationDuration: StateFlow<Int>
+
+ /**
* A view with the QS content ([QSContainerImpl]), managed by an instance of [QSImpl] tracked by
* the interactor.
*/
@@ -181,8 +204,35 @@
onBufferOverflow = BufferOverflow.DROP_OLDEST,
)
private val state = MutableStateFlow<QSSceneAdapter.State>(QSSceneAdapter.State.CLOSED)
- private val _isCustomizing: MutableStateFlow<Boolean> = MutableStateFlow(false)
- override val isCustomizing = _isCustomizing.asStateFlow()
+ private val _customizingState: MutableStateFlow<CustomizerState> =
+ MutableStateFlow(CustomizerState.Hidden)
+ val customizerState = _customizingState.asStateFlow()
+
+ override val isCustomizing: StateFlow<Boolean> =
+ customizerState
+ .map { it.isCustomizing }
+ .stateIn(
+ applicationScope,
+ SharingStarted.WhileSubscribed(),
+ customizerState.value.isCustomizing,
+ )
+ override val isCustomizerShowing: StateFlow<Boolean> =
+ customizerState
+ .map { it.isShowing }
+ .stateIn(
+ applicationScope,
+ SharingStarted.WhileSubscribed(),
+ customizerState.value.isShowing
+ )
+ override val customizerAnimationDuration: StateFlow<Int> =
+ customizerState
+ .map { (it as? CustomizerState.Animating)?.animationDuration?.toInt() ?: 0 }
+ .stateIn(
+ applicationScope,
+ SharingStarted.WhileSubscribed(),
+ (customizerState.value as? CustomizerState.Animating)?.animationDuration?.toInt()
+ ?: 0,
+ )
private val _qsImpl: MutableStateFlow<QSImpl?> = MutableStateFlow(null)
val qsImpl = _qsImpl.asStateFlow()
@@ -209,9 +259,9 @@
dumpManager.registerDumpable(this)
applicationScope.launch {
launch {
- state.sample(_isCustomizing, ::Pair).collect { (state, customizing) ->
+ state.sample(_customizingState, ::Pair).collect { (state, customizing) ->
qsImpl.value?.apply {
- if (state != QSSceneAdapter.State.QS && customizing) {
+ if (state != QSSceneAdapter.State.QS && customizing.isShowing) {
this@apply.closeCustomizerImmediately()
}
applyState(state)
@@ -243,14 +293,38 @@
}
}
- override fun setCustomizerAnimating(animating: Boolean) {}
+ override fun setCustomizerAnimating(animating: Boolean) {
+ if (_customizingState.value is CustomizerState.Animating && !animating) {
+ _customizingState.update {
+ if (it is CustomizerState.AnimatingIntoCustomizer) {
+ CustomizerState.Showing
+ } else {
+ CustomizerState.Hidden
+ }
+ }
+ }
+ }
override fun setCustomizerShowing(showing: Boolean) {
- _isCustomizing.value = showing
+ setCustomizerShowing(showing, 0L)
}
override fun setCustomizerShowing(showing: Boolean, animationDuration: Long) {
- setCustomizerShowing(showing)
+ _customizingState.update { _ ->
+ if (showing) {
+ if (animationDuration > 0) {
+ CustomizerState.AnimatingIntoCustomizer(animationDuration)
+ } else {
+ CustomizerState.Showing
+ }
+ } else {
+ if (animationDuration > 0) {
+ CustomizerState.AnimatingOutOfCustomizer(animationDuration)
+ } else {
+ CustomizerState.Hidden
+ }
+ }
+ }
}
override fun setDetailShowing(showing: Boolean) {}
@@ -302,9 +376,50 @@
override fun dump(pw: PrintWriter, args: Array<out String>) {
pw.apply {
println("Last state: ${state.value}")
- println("Customizing: ${isCustomizing.value}")
+ println("CustomizerState: ${_customizingState.value}")
println("QQS height: $qqsHeight")
println("QS height: $qsHeight")
}
}
}
+
+/** Current state of the customizer */
+sealed interface CustomizerState {
+
+ /**
+ * This indicates that some part of the customizer is showing. It could be animating in or out.
+ */
+ val isShowing: Boolean
+ get() = true
+
+ /**
+ * This indicates that we are currently customizing or animating into it. In particular, when
+ * animating out, this is false.
+ *
+ * @see QSCustomizer.isCustomizing
+ */
+ val isCustomizing: Boolean
+ get() = false
+
+ sealed interface Animating : CustomizerState {
+ val animationDuration: Long
+ }
+
+ /** Customizer is completely hidden, and not animating */
+ data object Hidden : CustomizerState {
+ override val isShowing = false
+ }
+
+ /** Customizer is completely showing, and not animating */
+ data object Showing : CustomizerState {
+ override val isCustomizing = true
+ }
+
+ /** Animating from [Hidden] into [Showing]. */
+ data class AnimatingIntoCustomizer(override val animationDuration: Long) : Animating {
+ override val isCustomizing = true
+ }
+
+ /** Animating from [Showing] into [Hidden]. */
+ data class AnimatingOutOfCustomizer(override val animationDuration: Long) : Animating
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModel.kt
index 257c4d5..17698f9d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModel.kt
@@ -79,13 +79,13 @@
combine(
deviceEntryInteractor.isUnlocked,
deviceEntryInteractor.canSwipeToEnter,
- qsSceneAdapter.isCustomizing,
+ qsSceneAdapter.isCustomizerShowing,
backScene,
- ) { isUnlocked, canSwipeToDismiss, isCustomizing, backScene ->
+ ) { isUnlocked, canSwipeToDismiss, isCustomizerShowing, backScene ->
destinationScenes(
isUnlocked,
canSwipeToDismiss,
- isCustomizing,
+ isCustomizerShowing,
backScene,
)
}
@@ -96,7 +96,7 @@
destinationScenes(
isUnlocked = deviceEntryInteractor.isUnlocked.value,
canSwipeToDismiss = deviceEntryInteractor.canSwipeToEnter.value,
- isCustomizing = qsSceneAdapter.isCustomizing.value,
+ isCustomizing = qsSceneAdapter.isCustomizerShowing.value,
backScene = backScene.value,
),
)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneViewModel.kt
new file mode 100644
index 0000000..d48d55d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneViewModel.kt
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.ui.viewmodel
+
+import com.android.compose.animation.scene.Back
+import com.android.compose.animation.scene.SceneKey
+import com.android.compose.animation.scene.Swipe
+import com.android.compose.animation.scene.UserAction
+import com.android.compose.animation.scene.UserActionResult
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.shade.ui.viewmodel.OverlayShadeViewModel
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.stateIn
+
+/** Models UI state and handles user input for the Quick Settings Shade scene. */
+@SysUISingleton
+class QuickSettingsShadeSceneViewModel
+@Inject
+constructor(
+ @Application private val applicationScope: CoroutineScope,
+ overlayShadeViewModel: OverlayShadeViewModel,
+) {
+ val destinationScenes: StateFlow<Map<UserAction, UserActionResult>> =
+ overlayShadeViewModel.backgroundScene
+ .map(::destinationScenes)
+ .stateIn(
+ scope = applicationScope,
+ started = SharingStarted.WhileSubscribed(),
+ initialValue = destinationScenes(overlayShadeViewModel.backgroundScene.value),
+ )
+
+ private fun destinationScenes(backgroundScene: SceneKey): Map<UserAction, UserActionResult> {
+ return mapOf(
+ Swipe.Up to backgroundScene,
+ Back to backgroundScene,
+ )
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index b92e8eb..faf2bbc 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -37,7 +37,6 @@
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_GOING_AWAY;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_TRACING_ENABLED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_VOICE_INTERACTION_WINDOW_SHOWING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_WAKEFULNESS_TRANSITION;
@@ -74,6 +73,7 @@
import androidx.annotation.NonNull;
+import com.android.compose.animation.scene.SceneKey;
import com.android.internal.accessibility.dialog.AccessibilityButtonChooserActivity;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.AssistUtils;
@@ -103,6 +103,8 @@
import com.android.systemui.settings.DisplayTracker;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.shade.ShadeViewController;
+import com.android.systemui.shade.domain.interactor.ShadeInteractor;
+import com.android.systemui.shade.shared.model.ShadeMode;
import com.android.systemui.shared.recents.IOverviewProxy;
import com.android.systemui.shared.recents.ISystemUiProxy;
import com.android.systemui.shared.system.QuickStepContract;
@@ -115,8 +117,6 @@
import com.android.wm.shell.desktopmode.DesktopModeStatus;
import com.android.wm.shell.sysui.ShellInterface;
-import dagger.Lazy;
-
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
@@ -128,6 +128,8 @@
import javax.inject.Inject;
import javax.inject.Provider;
+import dagger.Lazy;
+
/**
* Class to send information from overview to launcher with a binder.
*/
@@ -155,6 +157,7 @@
private final ScreenPinningRequest mScreenPinningRequest;
private final NotificationShadeWindowController mStatusBarWinController;
private final Provider<SceneInteractor> mSceneInteractor;
+ private final Provider<ShadeInteractor> mShadeInteractor;
private final Runnable mConnectionRunnable = () ->
internalConnectToCurrentUser("runnable: startConnectionToCurrentUser");
@@ -243,7 +246,9 @@
// Gesture was too short to be picked up by scene container touch
// handling; programmatically start the transition to shade scene.
mSceneInteractor.get().changeScene(
- Scenes.Shade, "short launcher swipe");
+ getShadeSceneKey(),
+ "short launcher swipe"
+ );
}
}
event.recycle();
@@ -261,7 +266,9 @@
"trackpad swipe");
} else if (action == ACTION_UP) {
mSceneInteractor.get().changeScene(
- Scenes.Shade, "short trackpad swipe");
+ getShadeSceneKey(),
+ "short trackpad swipe"
+ );
}
mStatusBarWinController.getWindowRootView().dispatchTouchEvent(event);
} else {
@@ -618,6 +625,7 @@
NotificationShadeWindowController statusBarWinController,
SysUiState sysUiState,
Provider<SceneInteractor> sceneInteractor,
+ Provider<ShadeInteractor> shadeInteractor,
UserTracker userTracker,
WakefulnessLifecycle wakefulnessLifecycle,
UiEventLogger uiEventLogger,
@@ -644,6 +652,7 @@
mScreenPinningRequest = screenPinningRequest;
mStatusBarWinController = statusBarWinController;
mSceneInteractor = sceneInteractor;
+ mShadeInteractor = shadeInteractor;
mUserTracker = userTracker;
mConnectionBackoffAttempts = 0;
mRecentsComponentName = ComponentName.unflattenFromString(context.getString(
@@ -691,15 +700,15 @@
// Listen for tracing state changes
@Override
public void onTracingStateChanged(boolean enabled) {
- mSysUiState.setFlag(SYSUI_STATE_TRACING_ENABLED, enabled)
- .commitUpdate(mContext.getDisplayId());
+ // TODO(b/286509643) Cleanup callers of this; Unused downstream
}
@Override
public void moveFocusedTaskToStageSplit(int displayId, boolean leftOrTop) {
if (mOverviewProxy != null) {
try {
- if (DesktopModeStatus.isEnabled() && (sysUiState.getFlags()
+ if (DesktopModeStatus.canEnterDesktopMode(mContext)
+ && (sysUiState.getFlags()
& SYSUI_STATE_FREEFORM_ACTIVE_IN_DESKTOP_MODE) != 0) {
return;
}
@@ -909,6 +918,12 @@
}
}
+ private SceneKey getShadeSceneKey() {
+ return mShadeInteractor.get().getShadeMode().getValue() == ShadeMode.dual()
+ ? Scenes.NotificationsShade
+ : Scenes.Shade;
+ }
+
private void notifyHomeRotationEnabled(boolean enabled) {
for (int i = mConnectionCallbacks.size() - 1; i >= 0; --i) {
mConnectionCallbacks.get(i).onHomeRotationEnabled(enabled);
diff --git a/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt b/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt
index 063a52c..8169dec 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt
@@ -17,10 +17,12 @@
package com.android.systemui.scene
import com.android.systemui.CoreStartable
+import com.android.systemui.notifications.ui.composable.NotificationsShadeSessionModule
import com.android.systemui.scene.domain.interactor.WindowRootViewVisibilityInteractor
import com.android.systemui.scene.domain.startable.SceneContainerStartable
import com.android.systemui.scene.shared.model.SceneContainerConfig
import com.android.systemui.scene.shared.model.Scenes
+import com.android.systemui.shade.shared.flag.DualShade
import dagger.Binds
import dagger.Module
import dagger.Provides
@@ -33,6 +35,8 @@
[
EmptySceneModule::class,
GoneSceneModule::class,
+ NotificationsShadeSceneModule::class,
+ NotificationsShadeSessionModule::class,
QuickSettingsSceneModule::class,
ShadeSceneModule::class,
],
@@ -59,18 +63,24 @@
// Note that this list is in z-order. The first one is the bottom-most and the
// last one is top-most.
sceneKeys =
- listOf(
+ listOfNotNull(
Scenes.Gone,
- Scenes.QuickSettings,
- Scenes.Shade,
+ Scenes.QuickSettings.takeUnless { DualShade.isEnabled },
+ Scenes.QuickSettingsShade.takeIf { DualShade.isEnabled },
+ Scenes.NotificationsShade.takeIf { DualShade.isEnabled },
+ Scenes.Shade.takeUnless { DualShade.isEnabled },
),
initialSceneKey = Scenes.Gone,
navigationDistances =
mapOf(
- Scenes.Gone to 0,
- Scenes.Shade to 1,
- Scenes.QuickSettings to 2,
- ),
+ Scenes.Gone to 0,
+ Scenes.NotificationsShade to 1.takeIf { DualShade.isEnabled },
+ Scenes.Shade to 1.takeUnless { DualShade.isEnabled },
+ Scenes.QuickSettingsShade to 2.takeIf { DualShade.isEnabled },
+ Scenes.QuickSettings to 2.takeUnless { DualShade.isEnabled },
+ )
+ .filterValues { it != null }
+ .mapValues { checkNotNull(it.value) }
)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt b/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt
index cd1b965..9bd2694 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt
@@ -18,10 +18,12 @@
import com.android.systemui.CoreStartable
import com.android.systemui.bouncer.shared.flag.ComposeBouncerFlagsModule
+import com.android.systemui.notifications.ui.composable.NotificationsShadeSessionModule
import com.android.systemui.scene.domain.interactor.WindowRootViewVisibilityInteractor
import com.android.systemui.scene.domain.startable.SceneContainerStartable
import com.android.systemui.scene.shared.model.SceneContainerConfig
import com.android.systemui.scene.shared.model.Scenes
+import com.android.systemui.shade.shared.flag.DualShade
import dagger.Binds
import dagger.Module
import dagger.Provides
@@ -40,6 +42,9 @@
LockscreenSceneModule::class,
QuickSettingsSceneModule::class,
ShadeSceneModule::class,
+ QuickSettingsShadeSceneModule::class,
+ NotificationsShadeSceneModule::class,
+ NotificationsShadeSessionModule::class,
],
)
interface SceneContainerFrameworkModule {
@@ -61,27 +66,33 @@
@Provides
fun containerConfig(): SceneContainerConfig {
return SceneContainerConfig(
- // Note that this list is in z-order. The first one is the bottom-most and the
- // last one is top-most.
+ // Note that this list is in z-order. The first one is the bottom-most and the last
+ // one is top-most.
sceneKeys =
- listOf(
+ listOfNotNull(
Scenes.Gone,
Scenes.Communal,
Scenes.Lockscreen,
Scenes.Bouncer,
- Scenes.QuickSettings,
- Scenes.Shade,
+ Scenes.QuickSettings.takeUnless { DualShade.isEnabled },
+ Scenes.QuickSettingsShade.takeIf { DualShade.isEnabled },
+ Scenes.NotificationsShade.takeIf { DualShade.isEnabled },
+ Scenes.Shade.takeUnless { DualShade.isEnabled },
),
initialSceneKey = Scenes.Lockscreen,
navigationDistances =
mapOf(
- Scenes.Gone to 0,
- Scenes.Lockscreen to 0,
- Scenes.Communal to 1,
- Scenes.Shade to 2,
- Scenes.QuickSettings to 3,
- Scenes.Bouncer to 4,
- ),
+ Scenes.Gone to 0,
+ Scenes.Lockscreen to 0,
+ Scenes.Communal to 1,
+ Scenes.NotificationsShade to 2.takeIf { DualShade.isEnabled },
+ Scenes.Shade to 2.takeUnless { DualShade.isEnabled },
+ Scenes.QuickSettingsShade to 3.takeIf { DualShade.isEnabled },
+ Scenes.QuickSettings to 3.takeUnless { DualShade.isEnabled },
+ Scenes.Bouncer to 4,
+ )
+ .filterValues { it != null }
+ .mapValues { checkNotNull(it.value) }
)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/data/model/SceneStack.kt b/packages/SystemUI/src/com/android/systemui/scene/data/model/SceneStack.kt
new file mode 100644
index 0000000..d3e529c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/scene/data/model/SceneStack.kt
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.scene.data.model
+
+import com.android.compose.animation.scene.SceneKey
+
+/** An immutable stack of [SceneKey]s backed by a singly-linked list. */
+sealed interface SceneStack
+
+private data object EmptyStack : SceneStack
+
+private data class StackedNodes(val head: SceneKey, val tail: SceneStack) : SceneStack
+
+/** Returns the scene at the head of the stack, or `null` if empty. O(1) */
+fun SceneStack.peek(): SceneKey? =
+ when (this) {
+ EmptyStack -> null
+ is StackedNodes -> head
+ }
+
+/** Returns a stack with the head removed, or `null` if empty. O(1) */
+fun SceneStack.pop(): SceneStack? =
+ when (this) {
+ EmptyStack -> null
+ is StackedNodes -> tail
+ }
+
+/** Returns a stack with [sceneKey] as the head on top of [this]. O(1) */
+fun SceneStack.push(sceneKey: SceneKey): SceneStack = StackedNodes(sceneKey, this)
+
+/** Returns an iterable that produces all elements in the stack, from head to tail. */
+fun SceneStack.asIterable(): Iterable<SceneKey> = Iterable {
+ iterator {
+ when (this@asIterable) {
+ EmptyStack -> {}
+ is StackedNodes -> {
+ yield(head)
+ yieldAll(tail.asIterable())
+ }
+ }
+ }
+}
+
+/**
+ * Returns a new [SceneStack] containing the given [scenes], ordered such that the first argument is
+ * the head returned from [peek], then the second, and so forth.
+ */
+fun sceneStackOf(vararg scenes: SceneKey): SceneStack {
+ var result: SceneStack = EmptyStack
+ for (sceneKey in scenes.reversed()) {
+ result = result.push(sceneKey)
+ }
+ return result
+}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/data/repository/SceneContainerRepository.kt b/packages/SystemUI/src/com/android/systemui/scene/data/repository/SceneContainerRepository.kt
index 5748ad4..eabc42b 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/data/repository/SceneContainerRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/data/repository/SceneContainerRepository.kt
@@ -87,6 +87,14 @@
)
}
+ fun snapToScene(
+ toScene: SceneKey,
+ ) {
+ dataSource.snapToScene(
+ toScene = toScene,
+ )
+ }
+
/** Sets whether the container is visible. */
fun setVisible(isVisible: Boolean) {
_isVisible.value = isVisible
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneBackInteractor.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneBackInteractor.kt
index f66d08f..c176cca 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneBackInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneBackInteractor.kt
@@ -18,13 +18,21 @@
import com.android.compose.animation.scene.SceneKey
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.scene.data.model.SceneStack
+import com.android.systemui.scene.data.model.asIterable
+import com.android.systemui.scene.data.model.peek
+import com.android.systemui.scene.data.model.pop
+import com.android.systemui.scene.data.model.push
+import com.android.systemui.scene.data.model.sceneStackOf
import com.android.systemui.scene.shared.logger.SceneLogger
import com.android.systemui.scene.shared.model.SceneContainerConfig
-import java.util.Stack
import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.update
@SysUISingleton
class SceneBackInteractor
@@ -33,7 +41,9 @@
private val logger: SceneLogger,
private val sceneContainerConfig: SceneContainerConfig,
) {
- private val _backScene = MutableStateFlow<SceneKey?>(null)
+ private val _backStack = MutableStateFlow(sceneStackOf())
+ val backStack: StateFlow<SceneStack> = _backStack.asStateFlow()
+
/**
* The scene to navigate to when the user triggers back navigation.
*
@@ -44,30 +54,30 @@
* illegal state to have scene implementation map to itself in its destination scene flow. Thus,
* scene implementations might wish to filter their own scene key out before using this.
*/
- val backScene: StateFlow<SceneKey?> = _backScene.asStateFlow()
-
- private val backStack = Stack<SceneKey>()
+ val backScene: Flow<SceneKey?> = backStack.map { it.peek() }
fun onSceneChange(from: SceneKey, to: SceneKey) {
check(from != to) { "from == to, from=${from.debugName}, to=${to.debugName}" }
when (stackOperation(from, to)) {
Clear -> {
- backStack.clear()
+ _backStack.value = sceneStackOf()
}
Push -> {
- backStack.push(from)
+ _backStack.update { s -> s.push(from) }
}
Pop -> {
- check(backStack.isNotEmpty()) { "Cannot pop ${from.debugName} when stack is empty" }
- val popped = backStack.pop()
- check(to == popped) {
- "Expected to pop ${to.debugName} but instead popped ${popped.debugName}"
+ _backStack.update { s ->
+ checkNotNull(s.pop()) { "Cannot pop ${from.debugName} when stack is empty" }
+ .also {
+ val popped = s.peek()
+ check(popped == to) {
+ "Expected to pop ${to.debugName} but instead popped ${popped?.debugName}"
+ }
+ }
}
}
}
-
- logger.logSceneBackStack(backStack)
- _backScene.value = peek()
+ logger.logSceneBackStack(backStack.value.asIterable())
}
private fun stackOperation(from: SceneKey, to: SceneKey): StackOperation {
@@ -92,14 +102,6 @@
}
}
- private fun peek(): SceneKey? {
- return if (backStack.isNotEmpty()) {
- backStack.peek()
- } else {
- null
- }
- }
-
private sealed interface StackOperation
private data object Clear : StackOperation
private data object Push : StackOperation
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneContainerOcclusionInteractor.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneContainerOcclusionInteractor.kt
index 5d60373..6bcd923 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneContainerOcclusionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneContainerOcclusionInteractor.kt
@@ -108,7 +108,7 @@
private val ObservableTransitionState.canBeOccluded: Boolean
get() =
when (this) {
- is ObservableTransitionState.Idle -> scene.canBeOccluded
+ is ObservableTransitionState.Idle -> currentScene.canBeOccluded
is ObservableTransitionState.Transition ->
fromScene.canBeOccluded && toScene.canBeOccluded
}
@@ -125,7 +125,9 @@
Scenes.Communal -> true
Scenes.Gone -> true
Scenes.Lockscreen -> true
+ Scenes.NotificationsShade -> false
Scenes.QuickSettings -> false
+ Scenes.QuickSettingsShade -> false
Scenes.Shade -> false
else -> error("SceneKey \"$this\" doesn't have a mapping for canBeOccluded!")
}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt
index 93cef61..08efe39 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt
@@ -162,19 +162,14 @@
loggingReason: String,
transitionKey: TransitionKey? = null,
) {
- if (!repository.allSceneKeys().contains(toScene)) {
- return
- }
-
- check(
- toScene != Scenes.Gone || deviceUnlockedInteractor.deviceUnlockStatus.value.isUnlocked
- ) {
- "Cannot change to the Gone scene while the device is locked. Logging reason for scene" +
- " change was: $loggingReason"
- }
-
val currentSceneKey = currentScene.value
- if (currentSceneKey == toScene) {
+ if (
+ !validateSceneChange(
+ from = currentSceneKey,
+ to = toScene,
+ loggingReason = loggingReason,
+ )
+ ) {
return
}
@@ -182,12 +177,44 @@
from = currentSceneKey,
to = toScene,
reason = loggingReason,
+ isInstant = false,
)
repository.changeScene(toScene, transitionKey)
}
/**
+ * Requests a scene change to the given scene.
+ *
+ * The change is instantaneous and not animated; it will be observable in the next frame and
+ * there will be no transition animation.
+ */
+ fun snapToScene(
+ toScene: SceneKey,
+ loggingReason: String,
+ ) {
+ val currentSceneKey = currentScene.value
+ if (
+ !validateSceneChange(
+ from = currentSceneKey,
+ to = toScene,
+ loggingReason = loggingReason,
+ )
+ ) {
+ return
+ }
+
+ logger.logSceneChangeRequested(
+ from = currentSceneKey,
+ to = toScene,
+ reason = loggingReason,
+ isInstant = true,
+ )
+
+ repository.snapToScene(toScene)
+ }
+
+ /**
* Sets the visibility of the container.
*
* Please do not call this from outside of the scene framework. If you are trying to force the
@@ -249,4 +276,32 @@
): Boolean {
return raw || isRemoteUserInteractionOngoing
}
+
+ /**
+ * Validates that the given scene change is allowed.
+ *
+ * Will throw a runtime exception for illegal states (for example, attempting to change to a
+ * scene that's not part of the current scene framework configuration).
+ *
+ * @param from The current scene being transitioned away from
+ * @param to The desired destination scene to transition to
+ * @param loggingReason The reason why the transition is requested, for logging purposes
+ * @return `true` if the scene change is valid; `false` if it shouldn't happen
+ */
+ private fun validateSceneChange(
+ from: SceneKey,
+ to: SceneKey,
+ loggingReason: String,
+ ): Boolean {
+ if (!repository.allSceneKeys().contains(to)) {
+ return false
+ }
+
+ check(to != Scenes.Gone || deviceUnlockedInteractor.deviceUnlockStatus.value.isUnlocked) {
+ "Cannot change to the Gone scene while the device is locked. Logging reason for scene" +
+ " change was: $loggingReason"
+ }
+
+ return from != to
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/WindowRootViewVisibilityInteractor.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/WindowRootViewVisibilityInteractor.kt
index 1cf1c18..9c2b992 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/WindowRootViewVisibilityInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/WindowRootViewVisibilityInteractor.kt
@@ -51,7 +51,7 @@
private val windowRootViewVisibilityRepository: WindowRootViewVisibilityRepository,
private val keyguardRepository: KeyguardRepository,
private val headsUpManager: HeadsUpManager,
- private val powerInteractor: PowerInteractor,
+ powerInteractor: PowerInteractor,
private val activeNotificationsInteractor: ActiveNotificationsInteractor,
sceneInteractorProvider: Provider<SceneInteractor>,
) : CoreStartable {
@@ -76,11 +76,18 @@
.map { state ->
when (state) {
is ObservableTransitionState.Idle ->
- state.scene == Scenes.Shade || state.scene == Scenes.Lockscreen
+ state.currentScene == Scenes.Shade ||
+ state.currentScene == Scenes.NotificationsShade ||
+ state.currentScene == Scenes.QuickSettingsShade ||
+ state.currentScene == Scenes.Lockscreen
is ObservableTransitionState.Transition ->
state.toScene == Scenes.Shade ||
+ state.toScene == Scenes.NotificationsShade ||
+ state.toScene == Scenes.QuickSettingsShade ||
state.toScene == Scenes.Lockscreen ||
state.fromScene == Scenes.Shade ||
+ state.fromScene == Scenes.NotificationsShade ||
+ state.fromScene == Scenes.QuickSettingsShade ||
state.fromScene == Scenes.Lockscreen
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
index d5de28a3..4a64277 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
@@ -45,9 +45,11 @@
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.plugins.FalsingManager.FalsingBeliefListener
import com.android.systemui.power.domain.interactor.PowerInteractor
+import com.android.systemui.scene.data.model.asIterable
import com.android.systemui.scene.domain.interactor.SceneBackInteractor
import com.android.systemui.scene.domain.interactor.SceneContainerOcclusionInteractor
import com.android.systemui.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.session.shared.SessionStorage
import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.scene.shared.logger.SceneLogger
import com.android.systemui.scene.shared.model.Scenes
@@ -116,6 +118,7 @@
private val shadeInteractor: ShadeInteractor,
private val uiEventLogger: UiEventLogger,
private val sceneBackInteractor: SceneBackInteractor,
+ private val shadeSessionStorage: SessionStorage,
) : CoreStartable {
private val centralSurfaces: CentralSurfaces?
get() = centralSurfacesOptLazy.get().getOrNull()
@@ -132,6 +135,7 @@
handleBouncerOverscroll()
hydrateWindowController()
hydrateBackStack()
+ resetShadeSessions()
} else {
sceneLogger.logFrameworkEnabled(
isEnabled = false,
@@ -150,6 +154,20 @@
}
}
+ private fun resetShadeSessions() {
+ applicationScope.launch {
+ sceneBackInteractor.backStack
+ // We are in a session if either Shade or QuickSettings is on the back stack
+ .map { backStack ->
+ backStack.asIterable().any { it == Scenes.Shade || it == Scenes.QuickSettings }
+ }
+ .distinctUntilChanged()
+ // Once a session has ended, clear the session storage.
+ .filter { inSession -> !inSession }
+ .collect { shadeSessionStorage.clear() }
+ }
+ }
+
/** Updates the visibility of the scene container. */
private fun hydrateVisibility() {
applicationScope.launch {
@@ -162,7 +180,7 @@
sceneInteractor.transitionState.mapNotNull { state ->
when (state) {
is ObservableTransitionState.Idle -> {
- if (state.scene != Scenes.Gone) {
+ if (state.currentScene != Scenes.Gone) {
true to "scene is not Gone"
} else {
false to "scene is Gone"
@@ -272,7 +290,7 @@
.mapNotNull { deviceUnlockStatus ->
val renderedScenes =
when (val transitionState = sceneInteractor.transitionState.value) {
- is ObservableTransitionState.Idle -> setOf(transitionState.scene)
+ is ObservableTransitionState.Idle -> setOf(transitionState.currentScene)
is ObservableTransitionState.Transition ->
setOf(
transitionState.fromScene,
@@ -307,8 +325,7 @@
Scenes.Gone to "device was unlocked in Bouncer scene"
} else {
val prevScene = previousScene.value
- (prevScene
- ?: Scenes.Gone) to
+ (prevScene ?: Scenes.Gone) to
"device was unlocked in Bouncer scene, from sceneKey=$prevScene"
}
isOnLockscreen ->
@@ -399,7 +416,7 @@
combine(
sceneInteractor.transitionState
.mapNotNull { it as? ObservableTransitionState.Idle }
- .map { it.scene }
+ .map { it.currentScene }
.distinctUntilChanged(),
occlusionInteractor.invisibleDueToOcclusion,
) { sceneKey, invisibleDueToOcclusion ->
@@ -424,7 +441,7 @@
applicationScope.launch {
sceneInteractor.transitionState
.mapNotNull { transitionState ->
- (transitionState as? ObservableTransitionState.Idle)?.scene
+ (transitionState as? ObservableTransitionState.Idle)?.currentScene
}
.distinctUntilChanged()
.collect { sceneKey ->
@@ -524,7 +541,7 @@
if (isDeviceLocked) {
sceneInteractor.transitionState
.mapNotNull { it as? ObservableTransitionState.Idle }
- .map { it.scene }
+ .map { it.currentScene }
.distinctUntilChanged()
.map { sceneKey ->
when (sceneKey) {
@@ -537,6 +554,7 @@
Scenes.Lockscreen -> true
Scenes.Bouncer -> false
Scenes.Shade -> false
+ Scenes.NotificationsShade -> false
else -> null
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/shared/logger/SceneLogger.kt b/packages/SystemUI/src/com/android/systemui/scene/shared/logger/SceneLogger.kt
index 5ebdd86..9d6720b 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/shared/logger/SceneLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/shared/logger/SceneLogger.kt
@@ -20,7 +20,6 @@
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.core.LogLevel
import com.android.systemui.log.dagger.SceneFrameworkLog
-import java.util.Stack
import javax.inject.Inject
class SceneLogger @Inject constructor(@SceneFrameworkLog private val logBuffer: LogBuffer) {
@@ -47,6 +46,7 @@
from: SceneKey,
to: SceneKey,
reason: String,
+ isInstant: Boolean,
) {
logBuffer.log(
tag = TAG,
@@ -55,8 +55,17 @@
str1 = from.toString()
str2 = to.toString()
str3 = reason
+ bool1 = isInstant
},
- messagePrinter = { "Scene change requested: $str1 → $str2, reason: $str3" },
+ messagePrinter = {
+ buildString {
+ append("Scene change requested: $str1 → $str2")
+ if (isInstant) {
+ append(" (instant)")
+ }
+ append(", reason: $str3")
+ }
+ },
)
}
@@ -116,7 +125,7 @@
)
}
- fun logSceneBackStack(backStack: Stack<SceneKey>) {
+ fun logSceneBackStack(backStack: Iterable<SceneKey>) {
logBuffer.log(
tag = TAG,
level = LogLevel.INFO,
diff --git a/packages/SystemUI/src/com/android/systemui/scene/shared/model/SceneDataSource.kt b/packages/SystemUI/src/com/android/systemui/scene/shared/model/SceneDataSource.kt
index 0e078d5..034da25 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/shared/model/SceneDataSource.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/shared/model/SceneDataSource.kt
@@ -40,4 +40,11 @@
toScene: SceneKey,
transitionKey: TransitionKey? = null,
)
+
+ /**
+ * Asks for an instant scene switch to [toScene], without an animated transition of any kind.
+ */
+ fun snapToScene(
+ toScene: SceneKey,
+ )
}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/shared/model/SceneDataSourceDelegator.kt b/packages/SystemUI/src/com/android/systemui/scene/shared/model/SceneDataSourceDelegator.kt
index 2fbcba9..43c3635 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/shared/model/SceneDataSourceDelegator.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/shared/model/SceneDataSourceDelegator.kt
@@ -56,6 +56,12 @@
)
}
+ override fun snapToScene(toScene: SceneKey) {
+ delegateMutable.value.snapToScene(
+ toScene = toScene,
+ )
+ }
+
/**
* Binds the current, dependency injection provided [SceneDataSource] to the given object.
*
@@ -77,5 +83,7 @@
MutableStateFlow(initialSceneKey).asStateFlow()
override fun changeScene(toScene: SceneKey, transitionKey: TransitionKey?) = Unit
+
+ override fun snapToScene(toScene: SceneKey) = Unit
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/shared/model/Scenes.kt b/packages/SystemUI/src/com/android/systemui/scene/shared/model/Scenes.kt
index 73fcca8..6d139da 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/shared/model/Scenes.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/shared/model/Scenes.kt
@@ -42,11 +42,58 @@
/** The lockscreen is the scene that shows when the device is locked. */
@JvmField val Lockscreen = SceneKey("lockscreen")
- /** The quick settings scene shows the quick setting tiles. */
+ /**
+ * The notifications shade scene primarily shows a scrollable list of notifications as an
+ * overlay UI.
+ *
+ * It's used only in the dual shade configuration, where there are two separate shades: one for
+ * notifications (this scene) and another for [QuickSettingsShade].
+ *
+ * It's not used in the single/accordion configuration (swipe down once to reveal the shade,
+ * swipe down again the to expand quick settings) or in the "split" shade configuration (on
+ * large screens or unfolded foldables, where notifications and quick settings are shown
+ * side-by-side in their own columns).
+ */
+ @JvmField val NotificationsShade = SceneKey("notifications_shade")
+
+ /**
+ * The quick settings scene shows the quick setting tiles.
+ *
+ * This scene is used for single/accordion configuration (swipe down once to reveal the shade,
+ * swipe down again the to expand quick settings).
+ *
+ * For the "split" shade configuration (on large screens or unfolded foldables, where
+ * notifications and quick settings are shown side-by-side in their own columns), the [Shade]
+ * scene is used].
+ *
+ * For the dual shade configuration, where there are two separate shades: one for notifications
+ * and one for quick settings, [NotificationsShade] and [QuickSettingsShade] scenes are used
+ * respectively.
+ */
@JvmField val QuickSettings = SceneKey("quick_settings")
/**
- * The shade is the scene whose primary purpose is to show a scrollable list of notifications.
+ * The quick settings shade scene shows the quick setting tiles as an overlay UI.
+ *
+ * It's used only in the dual shade configuration, where there are two separate shades: one for
+ * quick settings (this scene) and another for [NotificationsShade].
+ *
+ * It's not used in the single/accordion configuration (swipe down once to reveal the shade,
+ * swipe down again the to expand quick settings) or in the "split" shade configuration (on
+ * large screens or unfolded foldables, where notifications and quick settings are shown
+ * side-by-side in their own columns).
+ */
+ @JvmField val QuickSettingsShade = SceneKey("quick_settings_shade")
+
+ /**
+ * The shade is the scene that shows a scrollable list of notifications and the minimized
+ * version of quick settings (AKA "quick quick settings" or "QQS").
+ *
+ * This scene is used for single/accordion configuration (swipe down once to reveal the shade,
+ * swipe down again the to expand quick settings) and for the "split" shade configuration (on
+ * large screens or unfolded foldables, where notifications and quick settings are shown
+ * side-by-side in their own columns). For the dual shade configuration, where there are two
+ * separate shades: one for notifications and one for quick settings, other scenes are used.
*/
@JvmField val Shade = SceneKey("shade")
}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt
index 2ef9b73..78704e1 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt
@@ -182,12 +182,14 @@
right >= getDisplayWidth(context) -> CutoutLocation.RIGHT
else -> CutoutLocation.CENTER
}
+ val viewDisplayCutout = it?.displayCutout
DisplayCutout(
left,
top,
right,
bottom,
location,
+ viewDisplayCutout,
)
}
.stateIn(scope, SharingStarted.WhileSubscribed(), DisplayCutout())
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/GoneSceneViewModel.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/GoneSceneViewModel.kt
index 451fd67..b0af7f9 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/GoneSceneViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/GoneSceneViewModel.kt
@@ -51,7 +51,7 @@
private fun destinationScenes(shadeMode: ShadeMode): Map<UserAction, UserActionResult> {
return buildMap {
- if (shadeMode == ShadeMode.Single) {
+ if (shadeMode is ShadeMode.Single) {
this[
Swipe(
pointerCount = 2,
@@ -60,7 +60,20 @@
)] = UserActionResult(Scenes.QuickSettings)
}
- this[Swipe(direction = SwipeDirection.Down)] = UserActionResult(Scenes.Shade)
+ // TODO(b/338577208): Remove this once we add Dual Shade invocation zones.
+ if (shadeMode is ShadeMode.Dual) {
+ this[
+ Swipe(
+ pointerCount = 2,
+ fromSource = Edge.Top,
+ direction = SwipeDirection.Down,
+ )] = UserActionResult(Scenes.QuickSettingsShade)
+ }
+
+ this[Swipe(direction = SwipeDirection.Down)] =
+ UserActionResult(
+ if (shadeMode is ShadeMode.Dual) Scenes.NotificationsShade else Scenes.Shade
+ )
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt
index ef7829f..09c80b0 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt
@@ -124,8 +124,10 @@
when (toScene) {
Scenes.Bouncer -> Classifier.BOUNCER_UNLOCK
Scenes.Gone -> Classifier.UNLOCK
+ Scenes.NotificationsShade -> Classifier.NOTIFICATION_DRAG_DOWN
Scenes.Shade -> Classifier.NOTIFICATION_DRAG_DOWN
Scenes.QuickSettings -> Classifier.QUICK_SETTINGS
+ Scenes.QuickSettingsShade -> Classifier.QUICK_SETTINGS
else -> null
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionsProvider.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionsProvider.kt
index 07e143a..ef1d87d 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionsProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionsProvider.kt
@@ -87,7 +87,8 @@
AppCompatResources.getDrawable(context, R.drawable.ic_screenshot_edit),
context.resources.getString(R.string.screenshot_edit_label),
context.resources.getString(R.string.screenshot_edit_description),
- )
+ ),
+ showDuringEntrance = true,
) {
debugLog(LogConfig.DEBUG_ACTIONS) { "Edit tapped" }
uiEventLogger.log(SCREENSHOT_EDIT_TAPPED, 0, request.packageNameString)
@@ -105,7 +106,8 @@
AppCompatResources.getDrawable(context, R.drawable.ic_screenshot_share),
context.resources.getString(R.string.screenshot_share_label),
context.resources.getString(R.string.screenshot_share_description),
- )
+ ),
+ showDuringEntrance = true,
) {
debugLog(LogConfig.DEBUG_ACTIONS) { "Share tapped" }
uiEventLogger.log(SCREENSHOT_SHARE_TAPPED, 0, request.packageNameString)
@@ -125,7 +127,8 @@
AppCompatResources.getDrawable(context, R.drawable.ic_screenshot_scroll),
context.resources.getString(R.string.screenshot_scroll_label),
context.resources.getString(R.string.screenshot_scroll_label),
- )
+ ),
+ showDuringEntrance = true,
) {
onClick.run()
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
index 494fc9b..bd90de2 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
@@ -47,7 +47,6 @@
import android.graphics.Bitmap;
import android.graphics.Insets;
import android.graphics.Rect;
-import android.hardware.display.DisplayManager;
import android.net.Uri;
import android.os.Process;
import android.os.UserHandle;
@@ -208,8 +207,7 @@
@Nullable
private final ScreenshotSoundController mScreenshotSoundController;
private final PhoneWindow mWindow;
- private final DisplayManager mDisplayManager;
- private final int mDisplayId;
+ private final Display mDisplay;
private final ScrollCaptureExecutor mScrollCaptureExecutor;
private final ScreenshotNotificationSmartActionsProvider
mScreenshotNotificationSmartActionsProvider;
@@ -249,7 +247,6 @@
@AssistedInject
ScreenshotController(
Context context,
- DisplayManager displayManager,
WindowManager windowManager,
FeatureFlags flags,
ScreenshotViewProxy.Factory viewProxyFactory,
@@ -271,12 +268,13 @@
AssistContentRequester assistContentRequester,
MessageContainerController messageContainerController,
Provider<ScreenshotSoundController> screenshotSoundController,
- @Assisted int displayId,
+ @Assisted Display display,
@Assisted boolean showUIOnExternalDisplay
) {
mScreenshotSmartActions = screenshotSmartActions;
mActionsProviderFactory = actionsProviderFactory;
- mNotificationsController = screenshotNotificationsControllerFactory.create(displayId);
+ mNotificationsController = screenshotNotificationsControllerFactory.create(
+ display.getDisplayId());
mUiEventLogger = uiEventLogger;
mImageExporter = imageExporter;
mImageCapture = imageCapture;
@@ -290,11 +288,9 @@
mScreenshotHandler = timeoutHandler;
mScreenshotHandler.setDefaultTimeoutMillis(SCREENSHOT_CORNER_DEFAULT_TIMEOUT_MILLIS);
-
- mDisplayId = displayId;
- mDisplayManager = displayManager;
+ mDisplay = display;
mWindowManager = windowManager;
- final Context displayContext = context.createDisplayContext(getDisplay());
+ final Context displayContext = context.createDisplayContext(display);
mContext = (WindowContext) displayContext.createWindowContext(TYPE_SCREENSHOT, null);
mFlags = flags;
mActionIntentExecutor = actionIntentExecutor;
@@ -302,7 +298,7 @@
mMessageContainerController = messageContainerController;
mAssistContentRequester = assistContentRequester;
- mViewProxy = viewProxyFactory.getProxy(mContext, mDisplayId);
+ mViewProxy = viewProxyFactory.getProxy(mContext, mDisplay.getDisplayId());
mScreenshotHandler.setOnTimeoutRunnable(() -> {
if (DEBUG_UI) {
@@ -328,7 +324,7 @@
});
// Sound is only reproduced from the controller of the default display.
- if (displayId == Display.DEFAULT_DISPLAY) {
+ if (mDisplay.getDisplayId() == Display.DEFAULT_DISPLAY) {
mScreenshotSoundController = screenshotSoundController.get();
} else {
mScreenshotSoundController = null;
@@ -356,7 +352,7 @@
if (screenshot.getType() == WindowManager.TAKE_SCREENSHOT_FULLSCREEN
&& screenshot.getBitmap() == null) {
Rect bounds = getFullScreenRect();
- screenshot.setBitmap(mImageCapture.captureDisplay(mDisplayId, bounds));
+ screenshot.setBitmap(mImageCapture.captureDisplay(mDisplay.getDisplayId(), bounds));
screenshot.setScreenBounds(bounds);
}
@@ -459,7 +455,7 @@
}
private boolean shouldShowUi() {
- return mDisplayId == Display.DEFAULT_DISPLAY || mShowUIOnExternalDisplay;
+ return mDisplay.getDisplayId() == Display.DEFAULT_DISPLAY || mShowUIOnExternalDisplay;
}
void prepareViewForNewScreenshot(@NonNull ScreenshotData screenshot, String oldPackageName) {
@@ -618,7 +614,7 @@
private void requestScrollCapture(UserHandle owner) {
mScrollCaptureExecutor.requestScrollCapture(
- mDisplayId,
+ mDisplay.getDisplayId(),
mWindow.getDecorView().getWindowToken(),
(response) -> {
mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_LONG_SCREENSHOT_IMPRESSION,
@@ -641,7 +637,8 @@
}
mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_LONG_SCREENSHOT_REQUESTED, 0,
response.getPackageName());
- Bitmap newScreenshot = mImageCapture.captureDisplay(mDisplayId, getFullScreenRect());
+ Bitmap newScreenshot = mImageCapture.captureDisplay(mDisplay.getDisplayId(),
+ getFullScreenRect());
if (newScreenshot == null) {
Log.e(TAG, "Failed to capture current screenshot for scroll transition!");
return;
@@ -819,7 +816,8 @@
private void saveScreenshotInBackground(
ScreenshotData screenshot, UUID requestId, Consumer<Uri> finisher) {
ListenableFuture<ImageExporter.Result> future = mImageExporter.export(mBgExecutor,
- requestId, screenshot.getBitmap(), screenshot.getUserOrDefault(), mDisplayId);
+ requestId, screenshot.getBitmap(), screenshot.getUserOrDefault(),
+ mDisplay.getDisplayId());
future.addListener(() -> {
try {
ImageExporter.Result result = future.get();
@@ -861,7 +859,7 @@
data.mActionsReadyListener = actionsReadyListener;
data.mQuickShareActionsReadyListener = quickShareActionsReadyListener;
data.owner = owner;
- data.displayId = mDisplayId;
+ data.displayId = mDisplay.getDisplayId();
if (mSaveInBgTask != null) {
// just log success/failure for the pre-existing screenshot
@@ -986,13 +984,9 @@
}
}
- private Display getDisplay() {
- return mDisplayManager.getDisplay(mDisplayId);
- }
-
private Rect getFullScreenRect() {
DisplayMetrics displayMetrics = new DisplayMetrics();
- getDisplay().getRealMetrics(displayMetrics);
+ mDisplay.getRealMetrics(displayMetrics);
return new Rect(0, 0, displayMetrics.widthPixels, displayMetrics.heightPixels);
}
@@ -1026,12 +1020,12 @@
@AssistedFactory
public interface Factory {
/**
- * Creates an instance of the controller for that specific displayId.
+ * Creates an instance of the controller for that specific display.
*
- * @param displayId: display to capture
- * @param showUIOnExternalDisplay: Whether the UI should be shown if this is an external
- * display.
+ * @param display display to capture
+ * @param showUIOnExternalDisplay Whether the UI should be shown if this is an external
+ * display.
*/
- ScreenshotController create(int displayId, boolean showUIOnExternalDisplay);
+ ScreenshotController create(Display display, boolean showUIOnExternalDisplay);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotShelfViewProxy.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotShelfViewProxy.kt
index 9b754f3..412b089 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotShelfViewProxy.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotShelfViewProxy.kt
@@ -45,6 +45,7 @@
import com.android.systemui.screenshot.ui.ScreenshotAnimationController
import com.android.systemui.screenshot.ui.ScreenshotShelfView
import com.android.systemui.screenshot.ui.binder.ScreenshotShelfViewBinder
+import com.android.systemui.screenshot.ui.viewmodel.AnimationState
import com.android.systemui.screenshot.ui.viewmodel.ScreenshotViewModel
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
@@ -103,7 +104,7 @@
}
screenshotPreview = view.screenshotPreview
thumbnailObserver.setViews(
- view.screenshotPreview,
+ view.blurredScreenshotPreview,
view.requireViewById(R.id.screenshot_preview_border)
)
}
@@ -119,12 +120,19 @@
override fun updateOrientation(insets: WindowInsets) {}
override fun createScreenshotDropInAnimation(screenRect: Rect, showFlash: Boolean): Animator {
- val entrance = animationController.getEntranceAnimation(screenRect, showFlash)
- entrance.doOnStart { thumbnailObserver.onEntranceStarted() }
+ val entrance =
+ animationController.getEntranceAnimation(screenRect, showFlash) {
+ viewModel.setAnimationState(AnimationState.ENTRANCE_REVEAL)
+ }
+ entrance.doOnStart {
+ thumbnailObserver.onEntranceStarted()
+ viewModel.setAnimationState(AnimationState.ENTRANCE_STARTED)
+ }
entrance.doOnEnd {
// reset the timeout when animation finishes
callbacks?.onUserInteraction()
thumbnailObserver.onEntranceComplete()
+ viewModel.setAnimationState(AnimationState.ENTRANCE_COMPLETE)
}
return entrance
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotExecutor.kt b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotExecutor.kt
index e56a4f4..40d709d 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotExecutor.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotExecutor.kt
@@ -68,11 +68,13 @@
onSaved: (Uri?) -> Unit,
requestCallback: RequestCallback
) {
- val displayIds = getDisplaysToScreenshot(screenshotRequest.type)
+ val displays = getDisplaysToScreenshot(screenshotRequest.type)
val resultCallbackWrapper = MultiResultCallbackWrapper(requestCallback)
- displayIds.forEach { displayId: Int ->
+ displays.forEach { display ->
+ val displayId = display.displayId
Log.d(TAG, "Executing screenshot for display $displayId")
dispatchToController(
+ display = display,
rawScreenshotData = ScreenshotData.fromRequest(screenshotRequest, displayId),
onSaved =
if (displayId == Display.DEFAULT_DISPLAY) {
@@ -85,6 +87,7 @@
/** All logging should be triggered only by this method. */
private suspend fun dispatchToController(
+ display: Display,
rawScreenshotData: ScreenshotData,
onSaved: (Uri?) -> Unit,
callback: RequestCallback
@@ -104,8 +107,7 @@
logScreenshotRequested(screenshotData)
Log.d(TAG, "Screenshot request: $screenshotData")
try {
- getScreenshotController(screenshotData.displayId)
- .handleScreenshot(screenshotData, onSaved, callback)
+ getScreenshotController(display).handleScreenshot(screenshotData, onSaved, callback)
} catch (e: IllegalStateException) {
Log.e(TAG, "Error while ScreenshotController was handling ScreenshotData!", e)
onFailedScreenshotRequest(screenshotData, callback)
@@ -135,12 +137,13 @@
callback.reportError()
}
- private suspend fun getDisplaysToScreenshot(requestType: Int): List<Int> {
+ private suspend fun getDisplaysToScreenshot(requestType: Int): List<Display> {
+ val allDisplays = displays.first()
return if (requestType == TAKE_SCREENSHOT_PROVIDED_IMAGE) {
// If this is a provided image, let's show the UI on the default display only.
- listOf(Display.DEFAULT_DISPLAY)
+ allDisplays.filter { it.displayId == Display.DEFAULT_DISPLAY }
} else {
- displays.first().filter { it.type in ALLOWED_DISPLAY_TYPES }.map { it.displayId }
+ allDisplays.filter { it.type in ALLOWED_DISPLAY_TYPES }
}
}
@@ -170,9 +173,9 @@
screenshotControllers.clear()
}
- private fun getScreenshotController(id: Int): ScreenshotController {
- return screenshotControllers.computeIfAbsent(id) {
- screenshotControllerFactory.create(id, /* showUIOnExternalDisplay= */ false)
+ private fun getScreenshotController(display: Display): ScreenshotController {
+ return screenshotControllers.computeIfAbsent(display.displayId) {
+ screenshotControllerFactory.create(display, /* showUIOnExternalDisplay= */ false)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ui/ScreenshotAnimationController.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ui/ScreenshotAnimationController.kt
index 4eceb17..06e88f4 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ui/ScreenshotAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ui/ScreenshotAnimationController.kt
@@ -43,12 +43,15 @@
private val staticUI =
listOf<View>(
view.requireViewById(R.id.screenshot_preview_border),
- view.requireViewById(R.id.actions_container_background),
view.requireViewById(R.id.screenshot_badge),
view.requireViewById(R.id.screenshot_dismiss_button)
)
- fun getEntranceAnimation(bounds: Rect, showFlash: Boolean): Animator {
+ fun getEntranceAnimation(
+ bounds: Rect,
+ showFlash: Boolean,
+ onRevealMilestone: () -> Unit
+ ): Animator {
val entranceAnimation = AnimatorSet()
val previewAnimator = getPreviewAnimator(bounds)
@@ -71,6 +74,20 @@
entranceAnimation.doOnStart { screenshotPreview.visibility = View.INVISIBLE }
}
+ val actionsAnimator = getActionsAnimator()
+ entranceAnimation.play(actionsAnimator).with(previewAnimator)
+
+ // This isn't actually animating anything but is basically a timer for the first 200ms of
+ // the entrance animation. Using an animator here ensures that this is scaled if we change
+ // animator duration scales.
+ val revealMilestoneAnimator =
+ ValueAnimator.ofFloat(0f).apply {
+ duration = 0
+ startDelay = ACTION_REVEAL_DELAY_MS
+ doOnEnd { onRevealMilestone() }
+ }
+ entranceAnimation.play(revealMilestoneAnimator).with(actionsAnimator)
+
val fadeInAnimator = ValueAnimator.ofFloat(0f, 1f)
fadeInAnimator.addUpdateListener {
for (child in staticUI) {
@@ -123,6 +140,20 @@
animator?.cancel()
}
+ private fun getActionsAnimator(): Animator {
+ val startingOffset = view.height - actionContainer.top
+ val actionsYAnimator =
+ ValueAnimator.ofFloat(startingOffset.toFloat(), 0f).apply {
+ duration = PREVIEW_Y_ANIMATION_DURATION_MS
+ interpolator = fastOutSlowIn
+ }
+ actionsYAnimator.addUpdateListener {
+ actionContainer.translationY = it.animatedValue as Float
+ }
+ actionContainer.translationY = startingOffset.toFloat()
+ return actionsYAnimator
+ }
+
private fun getPreviewAnimator(bounds: Rect): Animator {
val targetPosition = Rect()
screenshotPreview.getHitRect(targetPosition)
@@ -183,5 +214,6 @@
private const val FLASH_OUT_DURATION_MS: Long = 217
private const val PREVIEW_X_ANIMATION_DURATION_MS: Long = 234
private const val PREVIEW_Y_ANIMATION_DURATION_MS: Long = 500
+ private const val ACTION_REVEAL_DELAY_MS: Long = 200
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ui/ScreenshotShelfView.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ui/ScreenshotShelfView.kt
index 4437bf5..916d50f 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ui/ScreenshotShelfView.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ui/ScreenshotShelfView.kt
@@ -35,6 +35,7 @@
class ScreenshotShelfView(context: Context, attrs: AttributeSet? = null) :
FrameLayout(context, attrs) {
lateinit var screenshotPreview: ImageView
+ lateinit var blurredScreenshotPreview: ImageView
private lateinit var screenshotStatic: ViewGroup
var onTouchInterceptListener: ((MotionEvent) -> Boolean)? = null
@@ -48,6 +49,7 @@
// Get focus so that the key events go to the layout.
isFocusableInTouchMode = true
screenshotPreview = requireViewById(R.id.screenshot_preview)
+ blurredScreenshotPreview = requireViewById(R.id.screenshot_preview_blur)
screenshotStatic = requireViewById(R.id.screenshot_static)
actionsContainerBackground = requireViewById(R.id.actions_container_background)
dismissButton = requireViewById(R.id.screenshot_dismiss_button)
@@ -75,15 +77,14 @@
fun updateInsets(insets: WindowInsets) {
val orientation = mContext.resources.configuration.orientation
val inPortrait = orientation == Configuration.ORIENTATION_PORTRAIT
- val p = screenshotStatic.layoutParams as LayoutParams
val cutout = insets.displayCutout
val navBarInsets = insets.getInsets(WindowInsets.Type.navigationBars())
if (cutout == null) {
- p.setMargins(0, 0, 0, navBarInsets.bottom)
+ screenshotStatic.setPadding(0, 0, 0, navBarInsets.bottom)
} else {
val waterfall = cutout.waterfallInsets
if (inPortrait) {
- p.setMargins(
+ screenshotStatic.setPadding(
waterfall.left,
max(cutout.safeInsetTop.toDouble(), waterfall.top.toDouble()).toInt(),
waterfall.right,
@@ -94,7 +95,7 @@
.toInt()
)
} else {
- p.setMargins(
+ screenshotStatic.setPadding(
max(cutout.safeInsetLeft.toDouble(), waterfall.left.toDouble()).toInt(),
waterfall.top,
max(cutout.safeInsetRight.toDouble(), waterfall.right.toDouble()).toInt(),
@@ -102,8 +103,6 @@
)
}
}
- screenshotStatic.layoutParams = p
- screenshotStatic.requestLayout()
}
private fun getSwipeRegion(): Region {
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ui/TransitioningIconDrawable.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ui/TransitioningIconDrawable.kt
new file mode 100644
index 0000000..0bc280c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ui/TransitioningIconDrawable.kt
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.screenshot.ui
+
+import android.animation.ValueAnimator
+import android.content.res.ColorStateList
+import android.graphics.Canvas
+import android.graphics.ColorFilter
+import android.graphics.drawable.Drawable
+import androidx.core.animation.doOnEnd
+import java.util.Objects
+
+/** */
+class TransitioningIconDrawable : Drawable() {
+ // The drawable for the current icon of this view. During icon transitions, this is the one
+ // being animated out.
+ private var drawable: Drawable? = null
+
+ // The incoming new icon. Only populated during transition animations (when drawable is also
+ // non-null).
+ private var enteringDrawable: Drawable? = null
+ private var colorFilter: ColorFilter? = null
+ private var tint: ColorStateList? = null
+ private var alpha = 255
+
+ private var transitionAnimator =
+ ValueAnimator.ofFloat(0f, 1f).also { it.doOnEnd { onTransitionComplete() } }
+
+ /**
+ * Set the drawable to be displayed, potentially animating the transition from one icon to the
+ * next.
+ */
+ fun setIcon(incomingDrawable: Drawable?) {
+ if (Objects.equals(drawable, incomingDrawable) && !transitionAnimator.isRunning) {
+ return
+ }
+
+ incomingDrawable?.colorFilter = colorFilter
+ incomingDrawable?.setTintList(tint)
+
+ if (drawable == null) {
+ // No existing icon drawn, just show the new one without a transition
+ drawable = incomingDrawable
+ invalidateSelf()
+ return
+ }
+
+ if (enteringDrawable != null) {
+ // There's already an entrance animation happening, just update the entering icon, not
+ // maintaining a queue or anything.
+ enteringDrawable = incomingDrawable
+ return
+ }
+
+ // There was already an icon, need to animate between icons.
+ enteringDrawable = incomingDrawable
+ transitionAnimator.setCurrentFraction(0f)
+ transitionAnimator.start()
+ invalidateSelf()
+ }
+
+ override fun draw(canvas: Canvas) {
+ // Scale the old one down, scale the new one up.
+ drawable?.let {
+ val scale =
+ if (transitionAnimator.isRunning) {
+ 1f - transitionAnimator.animatedFraction
+ } else {
+ 1f
+ }
+ drawScaledDrawable(it, canvas, scale)
+ }
+ enteringDrawable?.let {
+ val scale = transitionAnimator.animatedFraction
+ drawScaledDrawable(it, canvas, scale)
+ }
+
+ if (transitionAnimator.isRunning) {
+ invalidateSelf()
+ }
+ }
+
+ private fun drawScaledDrawable(drawable: Drawable, canvas: Canvas, scale: Float) {
+ drawable.bounds = getBounds()
+ canvas.save()
+ canvas.scale(
+ scale,
+ scale,
+ (drawable.intrinsicWidth / 2).toFloat(),
+ (drawable.intrinsicHeight / 2).toFloat()
+ )
+ drawable.draw(canvas)
+ canvas.restore()
+ }
+
+ private fun onTransitionComplete() {
+ drawable = enteringDrawable
+ enteringDrawable = null
+ invalidateSelf()
+ }
+
+ override fun setTintList(tint: ColorStateList?) {
+ super.setTintList(tint)
+ drawable?.setTintList(tint)
+ enteringDrawable?.setTintList(tint)
+ this.tint = tint
+ }
+
+ override fun setAlpha(alpha: Int) {
+ this.alpha = alpha
+ }
+
+ override fun setColorFilter(colorFilter: ColorFilter?) {
+ this.colorFilter = colorFilter
+ drawable?.colorFilter = colorFilter
+ enteringDrawable?.colorFilter = colorFilter
+ }
+
+ override fun getOpacity(): Int = alpha
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ui/binder/ActionButtonViewBinder.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ui/binder/ActionButtonViewBinder.kt
index 3c5a0ec..750bd53 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ui/binder/ActionButtonViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ui/binder/ActionButtonViewBinder.kt
@@ -21,6 +21,7 @@
import android.widget.LinearLayout
import android.widget.TextView
import com.android.systemui.res.R
+import com.android.systemui.screenshot.ui.TransitioningIconDrawable
import com.android.systemui.screenshot.ui.viewmodel.ActionButtonViewModel
object ActionButtonViewBinder {
@@ -28,7 +29,13 @@
fun bind(view: View, viewModel: ActionButtonViewModel) {
val iconView = view.requireViewById<ImageView>(R.id.overlay_action_chip_icon)
val textView = view.requireViewById<TextView>(R.id.overlay_action_chip_text)
- iconView.setImageDrawable(viewModel.appearance.icon)
+ if (iconView.drawable == null) {
+ iconView.setImageDrawable(TransitioningIconDrawable())
+ }
+ val drawable = iconView.drawable as? TransitioningIconDrawable
+ // Note we never re-bind a view to a different ActionButtonViewModel, different view
+ // models would remove/create separate views.
+ drawable?.setIcon(viewModel.appearance.icon)
textView.text = viewModel.appearance.label
setMargins(iconView, textView, viewModel.appearance.label?.isNotEmpty() ?: false)
if (viewModel.onClicked != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ui/binder/ScreenshotShelfViewBinder.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ui/binder/ScreenshotShelfViewBinder.kt
index 734a530..43c0107 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ui/binder/ScreenshotShelfViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ui/binder/ScreenshotShelfViewBinder.kt
@@ -31,6 +31,8 @@
import com.android.systemui.screenshot.ScreenshotEvent
import com.android.systemui.screenshot.ui.ScreenshotShelfView
import com.android.systemui.screenshot.ui.SwipeGestureListener
+import com.android.systemui.screenshot.ui.viewmodel.ActionButtonViewModel
+import com.android.systemui.screenshot.ui.viewmodel.AnimationState
import com.android.systemui.screenshot.ui.viewmodel.ScreenshotViewModel
import com.android.systemui.util.children
import kotlinx.coroutines.Dispatchers
@@ -55,9 +57,10 @@
view.onTouchInterceptListener = { swipeGestureListener.onMotionEvent(it) }
val previewView: ImageView = view.requireViewById(R.id.screenshot_preview)
+ val previewViewBlur: ImageView = view.requireViewById(R.id.screenshot_preview_blur)
val previewBorder = view.requireViewById<View>(R.id.screenshot_preview_border)
previewView.clipToOutline = true
- val actionsContainer: LinearLayout = view.requireViewById(R.id.screenshot_actions)
+ previewViewBlur.clipToOutline = true
val dismissButton = view.requireViewById<View>(R.id.screenshot_dismiss_button)
dismissButton.visibility = if (viewModel.showDismissButton) View.VISIBLE else View.GONE
dismissButton.setOnClickListener {
@@ -72,6 +75,7 @@
viewModel.preview.collect { bitmap ->
if (bitmap != null) {
setScreenshotBitmap(previewView, bitmap)
+ setScreenshotBitmap(previewViewBlur, bitmap)
previewView.visibility = View.VISIBLE
previewBorder.visibility = View.VISIBLE
} else {
@@ -87,44 +91,22 @@
}
launch {
viewModel.actions.collect { actions ->
- val visibleActions = actions.filter { it.visible }
-
- if (visibleActions.isNotEmpty()) {
- view
- .requireViewById<View>(R.id.actions_container_background)
- .visibility = View.VISIBLE
- }
-
- // Remove any buttons not in the new list, then do another pass to add
- // any new actions and update any that are already there.
- // This assumes that actions can never change order and that each action
- // ID is unique.
- val newIds = visibleActions.map { it.id }
-
- for (child in actionsContainer.children.toList()) {
- if (child.tag !in newIds) {
- actionsContainer.removeView(child)
- }
- }
-
- for ((index, action) in visibleActions.withIndex()) {
- val currentView: View? = actionsContainer.getChildAt(index)
- if (action.id == currentView?.tag) {
- // Same ID, update the display
- ActionButtonViewBinder.bind(currentView, action)
- } else {
- // Different ID. Removals have already happened so this must
- // mean that the new action must be inserted here.
- val actionButton =
- layoutInflater.inflate(
- R.layout.shelf_action_chip,
- actionsContainer,
- false
- )
- actionsContainer.addView(actionButton, index)
- ActionButtonViewBinder.bind(actionButton, action)
- }
- }
+ updateActions(
+ actions,
+ viewModel.animationState.value,
+ view,
+ layoutInflater
+ )
+ }
+ }
+ launch {
+ viewModel.animationState.collect { animationState ->
+ updateActions(
+ viewModel.actions.value,
+ animationState,
+ view,
+ layoutInflater
+ )
}
}
}
@@ -132,6 +114,53 @@
}
}
+ private fun updateActions(
+ actions: List<ActionButtonViewModel>,
+ animationState: AnimationState,
+ view: ScreenshotShelfView,
+ layoutInflater: LayoutInflater
+ ) {
+ val actionsContainer: LinearLayout = view.requireViewById(R.id.screenshot_actions)
+ val visibleActions =
+ actions.filter {
+ it.visible &&
+ (animationState == AnimationState.ENTRANCE_COMPLETE ||
+ animationState == AnimationState.ENTRANCE_REVEAL ||
+ it.showDuringEntrance)
+ }
+
+ if (visibleActions.isNotEmpty()) {
+ view.requireViewById<View>(R.id.actions_container_background).visibility = View.VISIBLE
+ }
+
+ // Remove any buttons not in the new list, then do another pass to add
+ // any new actions and update any that are already there.
+ // This assumes that actions can never change order and that each action
+ // ID is unique.
+ val newIds = visibleActions.map { it.id }
+
+ for (child in actionsContainer.children.toList()) {
+ if (child.tag !in newIds) {
+ actionsContainer.removeView(child)
+ }
+ }
+
+ for ((index, action) in visibleActions.withIndex()) {
+ val currentView: View? = actionsContainer.getChildAt(index)
+ if (action.id == currentView?.tag) {
+ // Same ID, update the display
+ ActionButtonViewBinder.bind(currentView, action)
+ } else {
+ // Different ID. Removals have already happened so this must
+ // mean that the new action must be inserted here.
+ val actionButton =
+ layoutInflater.inflate(R.layout.shelf_action_chip, actionsContainer, false)
+ actionsContainer.addView(actionButton, index)
+ ActionButtonViewBinder.bind(actionButton, action)
+ }
+ }
+ }
+
private fun setScreenshotBitmap(screenshotPreview: ImageView, bitmap: Bitmap) {
screenshotPreview.setImageBitmap(bitmap)
val hasPortraitAspectRatio = bitmap.width < bitmap.height
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ui/viewmodel/ActionButtonViewModel.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ui/viewmodel/ActionButtonViewModel.kt
index c5fa8db..364ab76 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ui/viewmodel/ActionButtonViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ui/viewmodel/ActionButtonViewModel.kt
@@ -20,6 +20,7 @@
val appearance: ActionButtonAppearance,
val id: Int,
val visible: Boolean,
+ val showDuringEntrance: Boolean,
val onClicked: (() -> Unit)?,
) {
companion object {
@@ -29,7 +30,14 @@
fun withNextId(
appearance: ActionButtonAppearance,
+ showDuringEntrance: Boolean,
onClicked: (() -> Unit)?
- ): ActionButtonViewModel = ActionButtonViewModel(appearance, getId(), true, onClicked)
+ ): ActionButtonViewModel =
+ ActionButtonViewModel(appearance, getId(), true, showDuringEntrance, onClicked)
+
+ fun withNextId(
+ appearance: ActionButtonAppearance,
+ onClicked: (() -> Unit)?
+ ): ActionButtonViewModel = withNextId(appearance, showDuringEntrance = true, onClicked)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ui/viewmodel/ScreenshotViewModel.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ui/viewmodel/ScreenshotViewModel.kt
index f67ad40..5f36f73 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ui/viewmodel/ScreenshotViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ui/viewmodel/ScreenshotViewModel.kt
@@ -29,6 +29,9 @@
val previewAction: StateFlow<(() -> Unit)?> = _previewAction
private val _actions = MutableStateFlow(emptyList<ActionButtonViewModel>())
val actions: StateFlow<List<ActionButtonViewModel>> = _actions
+ private val _animationState = MutableStateFlow(AnimationState.NOT_STARTED)
+ val animationState: StateFlow<AnimationState> = _animationState
+
val showDismissButton: Boolean
get() = accessibilityManager.isEnabled
@@ -40,9 +43,14 @@
_previewAction.value = onClick
}
- fun addAction(actionAppearance: ActionButtonAppearance, onClicked: (() -> Unit)): Int {
+ fun addAction(
+ actionAppearance: ActionButtonAppearance,
+ showDuringEntrance: Boolean,
+ onClicked: (() -> Unit)
+ ): Int {
val actionList = _actions.value.toMutableList()
- val action = ActionButtonViewModel.withNextId(actionAppearance, onClicked)
+ val action =
+ ActionButtonViewModel.withNextId(actionAppearance, showDuringEntrance, onClicked)
actionList.add(action)
_actions.value = actionList
return action.id
@@ -57,6 +65,7 @@
actionList[index].appearance,
actionId,
visible,
+ actionList[index].showDuringEntrance,
actionList[index].onClicked
)
_actions.value = actionList
@@ -74,6 +83,7 @@
appearance,
actionId,
actionList[index].visible,
+ actionList[index].showDuringEntrance,
actionList[index].onClicked
)
_actions.value = actionList
@@ -92,13 +102,26 @@
}
}
+ // TODO: this should be handled entirely within the view binder.
+ fun setAnimationState(state: AnimationState) {
+ _animationState.value = state
+ }
+
fun reset() {
_preview.value = null
_previewAction.value = null
_actions.value = listOf()
+ _animationState.value = AnimationState.NOT_STARTED
}
companion object {
const val TAG = "ScreenshotViewModel"
}
}
+
+enum class AnimationState {
+ NOT_STARTED,
+ ENTRANCE_STARTED, // The first 200ms of the entrance animation
+ ENTRANCE_REVEAL, // The rest of the entrance animation
+ ENTRANCE_COMPLETE,
+}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt b/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt
index ff5fdc6..6367d44b 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt
@@ -47,12 +47,13 @@
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.res.R
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.scene.shared.model.SceneDataSourceDelegator
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.statusbar.phone.SystemUIDialogFactory
-import com.android.systemui.util.kotlin.BooleanFlowOperators.and
+import com.android.systemui.util.kotlin.BooleanFlowOperators.allOf
+import com.android.systemui.util.kotlin.BooleanFlowOperators.anyOf
import com.android.systemui.util.kotlin.BooleanFlowOperators.not
-import com.android.systemui.util.kotlin.BooleanFlowOperators.or
import com.android.systemui.util.kotlin.collectFlow
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
@@ -69,7 +70,6 @@
private val communalInteractor: CommunalInteractor,
private val communalViewModel: CommunalViewModel,
private val dialogFactory: SystemUIDialogFactory,
- private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
private val keyguardInteractor: KeyguardInteractor,
private val shadeInteractor: ShadeInteractor,
private val powerManager: PowerManager,
@@ -102,12 +102,9 @@
private var rightEdgeSwipeRegionWidth: Int = 0
/**
- * True if we are currently tracking a gesture for opening the hub that started in the edge
- * swipe region.
+ * True if we are currently tracking a touch intercepted by the hub, either because the hub is
+ * open or being opened.
*/
- private var isTrackingOpenGesture = false
-
- /** True if we are currently tracking a touch on the hub while it's open. */
private var isTrackingHubTouch = false
/**
@@ -148,12 +145,12 @@
/** Returns a flow that tracks whether communal hub is available. */
fun communalAvailable(): Flow<Boolean> =
- or(communalInteractor.isCommunalAvailable, communalInteractor.editModeOpen)
+ anyOf(communalInteractor.isCommunalAvailable, communalInteractor.editModeOpen)
/**
* Creates the container view containing the glanceable hub UI.
*
- * @throws RuntimeException if [isEnabled] is false or the view is already initialized
+ * @throws RuntimeException if the view is already initialized
*/
fun initView(
context: Context,
@@ -197,6 +194,7 @@
/** Override for testing. */
@VisibleForTesting
internal fun initView(containerView: View): View {
+ SceneContainerFlag.assertInLegacyMode()
if (communalContainerView != null) {
throw RuntimeException("Communal view has already been initialized")
}
@@ -227,9 +225,11 @@
// BouncerSwipeTouchHandler has a larger gesture area than we want, set an exclusion area so
// the gesture area doesn't overlap with widgets.
- // TODO(b/323035776): adjust gesture areaa for portrait mode
+ // TODO(b/323035776): adjust gesture area for portrait mode
containerView.repeatWhenAttached {
- repeatOnLifecycle(Lifecycle.State.CREATED) {
+ // Run when the touch handling lifecycle is RESUMED, meaning the hub is visible and not
+ // occluded.
+ lifecycleRegistry.repeatOnLifecycle(Lifecycle.State.RESUMED) {
val exclusionRect =
Rect(
0,
@@ -242,28 +242,35 @@
}
}
+ // Listen to bouncer visibility directly as these flows become true as soon as any portion
+ // of the bouncers are visible when the transition starts. The keyguard transition state
+ // only changes once transitions are fully finished, which would mean touches during a
+ // transition to the bouncer would be incorrectly intercepted by the hub.
collectFlow(
containerView,
- keyguardTransitionInteractor.isFinishedInStateWhere(KeyguardState::isBouncerState),
+ anyOf(
+ keyguardInteractor.primaryBouncerShowing,
+ keyguardInteractor.alternateBouncerShowing
+ ),
{
anyBouncerShowing = it
- updateLifecycleState()
+ updateTouchHandlingState()
}
)
collectFlow(
containerView,
- communalInteractor.isCommunalShowing,
+ communalInteractor.isCommunalVisible,
{
hubShowing = it
- updateLifecycleState()
+ updateTouchHandlingState()
}
)
collectFlow(
containerView,
- and(shadeInteractor.isAnyFullyExpanded, not(shadeInteractor.isUserInteracting)),
+ allOf(shadeInteractor.isAnyFullyExpanded, not(shadeInteractor.isUserInteracting)),
{
shadeShowing = it
- updateLifecycleState()
+ updateTouchHandlingState()
}
)
collectFlow(containerView, keyguardInteractor.isDreaming, { isDreaming = it })
@@ -276,18 +283,28 @@
/**
* Updates the lifecycle stored by the [lifecycleRegistry] to control when the [touchMonitor]
* should listen for and intercept top and bottom swipes.
+ *
+ * Also clears gesture exclusion zones when the hub is occluded or gone.
*/
- private fun updateLifecycleState() {
+ private fun updateTouchHandlingState() {
val shouldInterceptGestures = hubShowing && !(shadeShowing || anyBouncerShowing)
if (shouldInterceptGestures) {
lifecycleRegistry.currentState = Lifecycle.State.RESUMED
} else {
+ // Hub is either occluded or no longer showing, turn off touch handling.
lifecycleRegistry.currentState = Lifecycle.State.STARTED
+
+ // Clear exclusion rects if the hub is not showing or is covered, so we don't interfere
+ // with back gestures when the bouncer or shade. We do this here instead of with
+ // repeatOnLifecycle as repeatOnLifecycle does not run when going from RESUMED back to
+ // STARTED, only when going from CREATED to STARTED.
+ communalContainerView!!.systemGestureExclusionRects = emptyList()
}
}
/** Removes the container view from its parent. */
fun disposeView() {
+ SceneContainerFlag.assertInLegacyMode()
communalContainerView?.let {
(it.parent as ViewGroup).removeView(it)
lifecycleRegistry.currentState = Lifecycle.State.CREATED
@@ -305,20 +322,11 @@
* to be fully in control of its own touch handling.
*/
fun onTouchEvent(ev: MotionEvent): Boolean {
+ SceneContainerFlag.assertInLegacyMode()
return communalContainerView?.let { handleTouchEventOnCommunalView(it, ev) } ?: false
}
private fun handleTouchEventOnCommunalView(view: View, ev: MotionEvent): Boolean {
- // If the hub is fully visible, send all touch events to it, other than top and bottom edge
- // swipes.
- return if (hubShowing) {
- handleHubOpenTouch(view, ev)
- } else {
- handleHubClosedTouch(view, ev)
- }
- }
-
- private fun handleHubOpenTouch(view: View, ev: MotionEvent): Boolean {
val isDown = ev.actionMasked == MotionEvent.ACTION_DOWN
val isUp = ev.actionMasked == MotionEvent.ACTION_UP
val isCancel = ev.actionMasked == MotionEvent.ACTION_CANCEL
@@ -326,50 +334,18 @@
val hubOccluded = anyBouncerShowing || shadeShowing
if (isDown && !hubOccluded) {
- // Only intercept down events if the hub isn't occluded by the bouncer or
- // notification shade.
- isTrackingHubTouch = true
- }
-
- if (isTrackingHubTouch) {
- // Tracking a touch on the hub UI itself.
- if (isUp || isCancel) {
- isTrackingHubTouch = false
- }
- dispatchTouchEvent(view, ev)
- // Return true regardless of dispatch result as some touches at the start of a
- // gesture
- // may return false from dispatchTouchEvent.
- return true
- }
-
- return false
- }
-
- private fun handleHubClosedTouch(view: View, ev: MotionEvent): Boolean {
- val isDown = ev.actionMasked == MotionEvent.ACTION_DOWN
- val isUp = ev.actionMasked == MotionEvent.ACTION_UP
- val isCancel = ev.actionMasked == MotionEvent.ACTION_CANCEL
-
- val hubOccluded = anyBouncerShowing || shadeShowing
-
- if (rightEdgeSwipeRegionWidth == 0) {
- // If the edge region width has not been read yet for whatever reason, don't bother
- // intercepting touches to open the hub.
- return false
- }
-
- if (isDown && !hubOccluded) {
val x = ev.rawX
val inOpeningSwipeRegion: Boolean = x >= view.width - rightEdgeSwipeRegionWidth
- if (inOpeningSwipeRegion) {
- isTrackingOpenGesture = true
+ if (inOpeningSwipeRegion || hubShowing) {
+ // Steal touch events when the hub is open, or if the touch started in the opening
+ // gesture region.
+ isTrackingHubTouch = true
}
}
- if (isTrackingOpenGesture) {
+ if (isTrackingHubTouch) {
if (isUp || isCancel) {
- isTrackingOpenGesture = false
+ isTrackingHubTouch = false
}
dispatchTouchEvent(view, ev)
// Return true regardless of dispatch result as some touches at the start of a gesture
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index 4d4d177..7051d5f 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -25,6 +25,7 @@
import static com.android.keyguard.KeyguardClockSwitch.LARGE;
import static com.android.keyguard.KeyguardClockSwitch.SMALL;
import static com.android.systemui.Flags.predictiveBackAnimateShade;
+import static com.android.systemui.Flags.shadeCollapseActivityLaunchFix;
import static com.android.systemui.Flags.smartspaceRelocateToBottom;
import static com.android.systemui.classifier.Classifier.BOUNCER_UNLOCK;
import static com.android.systemui.classifier.Classifier.GENERIC;
@@ -619,6 +620,7 @@
private int mDreamingToLockscreenTransitionTranslationY;
private int mLockscreenToDreamingTransitionTranslationY;
private int mGoneToDreamingTransitionTranslationY;
+ private boolean mForceFlingAnimationForTest = false;
private final SplitShadeStateController mSplitShadeStateController;
private final Runnable mFlingCollapseRunnable = () -> fling(0, false /* expand */,
mNextCollapseSpeedUpFactor, false /* expandBecauseOfFalsing */);
@@ -2217,11 +2219,19 @@
}
}
});
+ if (!mScrimController.isScreenOn() && !mForceFlingAnimationForTest) {
+ animator.setDuration(1);
+ }
setAnimator(animator);
animator.start();
}
@VisibleForTesting
+ void setForceFlingAnimationForTest(boolean force) {
+ mForceFlingAnimationForTest = force;
+ }
+
+ @VisibleForTesting
void onFlingEnd(boolean cancelled) {
mIsFlinging = false;
// No overshoot when the animation ends
@@ -4102,7 +4112,11 @@
@Override
public boolean canBeCollapsed() {
- return !isFullyCollapsed() && !isTracking() && !isClosing();
+ return !isFullyCollapsed() && !isTracking() && !isClosing()
+ // Don't try to collapse if on keyguard, as the expansion fraction is 1 in this
+ // case.
+ && !(shadeCollapseActivityLaunchFix() && mExpandedFraction == 1f
+ && mBarState == KEYGUARD);
}
public void instantCollapse() {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
index 4a636d2..3eb4389 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
@@ -412,9 +412,9 @@
}
if (state.bouncerShowing) {
- mLpChanged.inputFeatures |= LayoutParams.INPUT_FEATURE_SENSITIVE_FOR_TRACING;
+ mLpChanged.inputFeatures |= LayoutParams.INPUT_FEATURE_SENSITIVE_FOR_PRIVACY;
} else {
- mLpChanged.inputFeatures &= ~LayoutParams.INPUT_FEATURE_SENSITIVE_FOR_TRACING;
+ mLpChanged.inputFeatures &= ~LayoutParams.INPUT_FEATURE_SENSITIVE_FOR_PRIVACY;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
index 44f86da..b50a3cd 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
@@ -52,6 +52,7 @@
import com.android.systemui.keyguard.shared.model.TransitionState;
import com.android.systemui.keyguard.shared.model.TransitionStep;
import com.android.systemui.res.R;
+import com.android.systemui.scene.shared.flag.SceneContainerFlag;
import com.android.systemui.shade.domain.interactor.PanelExpansionInteractor;
import com.android.systemui.shared.animation.DisableSubpixelTextTransitionListener;
import com.android.systemui.statusbar.DragDownHelper;
@@ -357,7 +358,9 @@
mFalsingCollector.onTouchEvent(ev);
mPulsingWakeupGestureHandler.onTouchEvent(ev);
- if (mGlanceableHubContainerController.onTouchEvent(ev)) {
+ if (!SceneContainerFlag.isEnabled()
+ && mGlanceableHubContainerController.onTouchEvent(ev)) {
+ // GlanceableHubContainerController is only used pre-flexiglass.
return logDownDispatch(ev, "dispatched to glanceable hub container", true);
}
if (mDreamingWakeupGestureHandler != null
@@ -621,6 +624,10 @@
* The layout lives in {@link R.id.communal_ui_stub}.
*/
public void setupCommunalHubLayout() {
+ if (SceneContainerFlag.isEnabled()) {
+ // GlanceableHubContainerController is only used pre-flexiglass.
+ return;
+ }
collectFlow(
mView,
mGlanceableHubContainerController.communalAvailable(),
diff --git a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsControllerSceneImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsControllerSceneImpl.kt
index 3462993..864e39a 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsControllerSceneImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsControllerSceneImpl.kt
@@ -33,7 +33,7 @@
get() = shadeInteractor.isQsExpanded.value
override val isCustomizing: Boolean
- get() = qsSceneAdapter.isCustomizing.value
+ get() = qsSceneAdapter.isCustomizerShowing.value
@Deprecated("specific to legacy touch handling")
override fun shouldQuickSettingsIntercept(x: Float, y: Float, yDiff: Float): Boolean {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerSceneImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerSceneImpl.kt
index 8c15817..d2c93da 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerSceneImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerSceneImpl.kt
@@ -28,10 +28,10 @@
import com.android.systemui.log.dagger.ShadeTouchLog
import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.scene.shared.model.Scenes
-import com.android.systemui.scene.shared.model.TransitionKeys.CollapseShadeInstantly
import com.android.systemui.scene.shared.model.TransitionKeys.SlightlyFasterShadeCollapse
import com.android.systemui.shade.ShadeController.ShadeVisibilityListener
import com.android.systemui.shade.domain.interactor.ShadeInteractor
+import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.statusbar.CommandQueue
import com.android.systemui.statusbar.NotificationShadeWindowController
import com.android.systemui.statusbar.VibratorHelper
@@ -99,11 +99,9 @@
}
override fun instantCollapseShade() {
- // TODO(b/325602936) add support for instant transition
- sceneInteractor.changeScene(
+ sceneInteractor.snapToScene(
getCollapseDestinationScene(),
"hide shade",
- CollapseShadeInstantly,
)
}
@@ -194,11 +192,19 @@
}
override fun expandToNotifications() {
- sceneInteractor.changeScene(Scenes.Shade, "ShadeController.animateExpandShade")
+ val shadeMode = shadeInteractor.shadeMode.value
+ sceneInteractor.changeScene(
+ if (shadeMode is ShadeMode.Dual) Scenes.NotificationsShade else Scenes.Shade,
+ "ShadeController.animateExpandShade"
+ )
}
override fun expandToQs() {
- sceneInteractor.changeScene(Scenes.QuickSettings, "ShadeController.animateExpandQs")
+ val shadeMode = shadeInteractor.shadeMode.value
+ sceneInteractor.changeScene(
+ if (shadeMode is ShadeMode.Dual) Scenes.QuickSettingsShade else Scenes.QuickSettings,
+ "ShadeController.animateExpandQs"
+ )
}
override fun setVisibilityListener(listener: ShadeVisibilityListener) {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeRepository.kt b/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeRepository.kt
index b934d63..7e1a310 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeRepository.kt
@@ -16,6 +16,7 @@
package com.android.systemui.shade.data.repository
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.shade.shared.flag.DualShade
import com.android.systemui.shade.shared.model.ShadeMode
import javax.inject.Inject
import kotlinx.coroutines.flow.MutableStateFlow
@@ -219,7 +220,7 @@
@Deprecated("Use ShadeInteractor instead")
override val legacyQsFullscreen: StateFlow<Boolean> = _legacyQsFullscreen.asStateFlow()
- val _shadeMode = MutableStateFlow<ShadeMode>(ShadeMode.Single)
+ val _shadeMode = MutableStateFlow(if (DualShade.isEnabled) ShadeMode.Dual else ShadeMode.Single)
override val shadeMode: StateFlow<ShadeMode> = _shadeMode.asStateFlow()
override fun setShadeMode(shadeMode: ShadeMode) {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/PanelExpansionInteractorImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/PanelExpansionInteractorImpl.kt
index 58bcd2e..8006e94 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/PanelExpansionInteractorImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/PanelExpansionInteractorImpl.kt
@@ -55,7 +55,7 @@
when (state) {
is ObservableTransitionState.Idle ->
flowOf(
- if (state.scene != Scenes.Gone) {
+ if (state.currentScene != Scenes.Gone) {
// When resting on a non-Gone scene, the panel is fully expanded.
1f
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeBackActionInteractorImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeBackActionInteractorImpl.kt
index 3a8ba7a..c9949cd 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeBackActionInteractorImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeBackActionInteractorImpl.kt
@@ -19,6 +19,7 @@
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.scene.shared.model.Scenes
+import com.android.systemui.shade.shared.model.ShadeMode
import javax.inject.Inject
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -34,7 +35,7 @@
override fun animateCollapseQs(fullyCollapse: Boolean) {
if (shadeInteractor.isQsExpanded.value) {
val key =
- if (fullyCollapse) {
+ if (fullyCollapse || shadeInteractor.shadeMode.value is ShadeMode.Dual) {
if (deviceEntryInteractor.isDeviceEntered.value) {
Scenes.Gone
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImpl.kt
index 7f35f17..53c10a3 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImpl.kt
@@ -90,7 +90,7 @@
sceneInteractor.transitionState
.map { state ->
when (state) {
- is ObservableTransitionState.Idle -> state.scene == Scenes.QuickSettings
+ is ObservableTransitionState.Idle -> state.currentScene == Scenes.QuickSettings
is ObservableTransitionState.Transition -> false
}
}
@@ -122,7 +122,7 @@
.flatMapLatest { state ->
when (state) {
is ObservableTransitionState.Idle ->
- if (state.scene == sceneKey) {
+ if (state.currentScene == sceneKey) {
flowOf(1f)
} else {
flowOf(0f)
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeLockscreenInteractorImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeLockscreenInteractorImpl.kt
index 6a8b9ee..9885fe4 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeLockscreenInteractorImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeLockscreenInteractorImpl.kt
@@ -21,6 +21,7 @@
import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.shade.data.repository.ShadeRepository
+import com.android.systemui.shade.shared.model.ShadeMode
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.delay
@@ -95,8 +96,9 @@
}
private fun changeToShadeScene() {
+ val shadeMode = shadeInteractor.shadeMode.value
sceneInteractor.changeScene(
- Scenes.Shade,
+ if (shadeMode is ShadeMode.Dual) Scenes.NotificationsShade else Scenes.Shade,
"ShadeLockscreenInteractorImpl.expandToNotifications",
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/startable/ShadeStartable.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/startable/ShadeStartable.kt
index f3802da..3f4bcba 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/startable/ShadeStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/startable/ShadeStartable.kt
@@ -29,6 +29,7 @@
import com.android.systemui.shade.TouchLogger.Companion.logTouchesTo
import com.android.systemui.shade.data.repository.ShadeRepository
import com.android.systemui.shade.domain.interactor.PanelExpansionInteractor
+import com.android.systemui.shade.shared.flag.DualShade
import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.shade.transition.ScrimShadeTransitionController
import com.android.systemui.statusbar.policy.SplitShadeStateController
@@ -67,19 +68,24 @@
private fun hydrateShadeExpansionStateManager() {
if (SceneContainerFlag.isEnabled) {
combine(
- panelExpansionInteractorProvider.get().legacyPanelExpansion,
- sceneInteractorProvider.get().isTransitionUserInputOngoing,
- ) { panelExpansion, tracking ->
- shadeExpansionStateManager.onPanelExpansionChanged(
- fraction = panelExpansion,
- expanded = panelExpansion > 0f,
- tracking = tracking,
- )
- }.launchIn(applicationScope)
+ panelExpansionInteractorProvider.get().legacyPanelExpansion,
+ sceneInteractorProvider.get().isTransitionUserInputOngoing,
+ ) { panelExpansion, tracking ->
+ shadeExpansionStateManager.onPanelExpansionChanged(
+ fraction = panelExpansion,
+ expanded = panelExpansion > 0f,
+ tracking = tracking,
+ )
+ }
+ .launchIn(applicationScope)
}
}
private fun hydrateShadeMode() {
+ if (DualShade.isEnabled) {
+ shadeRepository.setShadeMode(ShadeMode.Dual)
+ return
+ }
applicationScope.launch {
configurationRepository.onAnyConfigurationChange
// Force initial collection.
@@ -90,11 +96,7 @@
}
.collect { isSplitShade ->
shadeRepository.setShadeMode(
- if (isSplitShade) {
- ShadeMode.Split
- } else {
- ShadeMode.Single
- }
+ if (isSplitShade) ShadeMode.Split else ShadeMode.Single
)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/shared/model/ShadeMode.kt b/packages/SystemUI/src/com/android/systemui/shade/shared/model/ShadeMode.kt
index 3451eaf..8214a24 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/shared/model/ShadeMode.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/shared/model/ShadeMode.kt
@@ -38,4 +38,8 @@
* a space on a small screen or folded device.
*/
data object Dual : ShadeMode
+
+ companion object {
+ @JvmStatic fun dual(): Dual = Dual
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/OverlayShadeViewModel.kt b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/OverlayShadeViewModel.kt
new file mode 100644
index 0000000..b8dd628
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/OverlayShadeViewModel.kt
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shade.ui.viewmodel
+
+import com.android.compose.animation.scene.SceneKey
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
+import com.android.systemui.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.shared.model.Scenes
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.stateIn
+
+/**
+ * Models UI state and handles user input for the overlay shade UI, which shows a shade as an
+ * overlay on top of another scene UI.
+ */
+@OptIn(ExperimentalCoroutinesApi::class)
+@SysUISingleton
+class OverlayShadeViewModel
+@Inject
+constructor(
+ @Application private val applicationScope: CoroutineScope,
+ private val sceneInteractor: SceneInteractor,
+ deviceEntryInteractor: DeviceEntryInteractor,
+) {
+ /** The scene to show in the background when the overlay shade is open. */
+ val backgroundScene: StateFlow<SceneKey> =
+ deviceEntryInteractor.isDeviceEntered
+ .map(::backgroundScene)
+ .stateIn(
+ scope = applicationScope,
+ started = SharingStarted.WhileSubscribed(),
+ initialValue = backgroundScene(deviceEntryInteractor.isDeviceEntered.value)
+ )
+
+ /** Notifies that the user has clicked the semi-transparent background scrim. */
+ fun onScrimClicked() {
+ sceneInteractor.changeScene(
+ toScene = backgroundScene.value,
+ loggingReason = "Shade scrim clicked",
+ )
+ }
+
+ private fun backgroundScene(isDeviceEntered: Boolean): SceneKey {
+ return if (isDeviceEntered) Scenes.Gone else Scenes.Lockscreen
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModel.kt b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModel.kt
index 5b76acb..ac76bec 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModel.kt
@@ -72,13 +72,13 @@
deviceEntryInteractor.isUnlocked,
deviceEntryInteractor.canSwipeToEnter,
shadeInteractor.shadeMode,
- qsSceneAdapter.isCustomizing
- ) { isUnlocked, canSwipeToDismiss, shadeMode, isCustomizing ->
+ qsSceneAdapter.isCustomizerShowing
+ ) { isUnlocked, canSwipeToDismiss, shadeMode, isCustomizerShowing ->
destinationScenes(
isUnlocked = isUnlocked,
canSwipeToDismiss = canSwipeToDismiss,
shadeMode = shadeMode,
- isCustomizing = isCustomizing
+ isCustomizing = isCustomizerShowing
)
}
.stateIn(
@@ -89,7 +89,7 @@
isUnlocked = deviceEntryInteractor.isUnlocked.value,
canSwipeToDismiss = deviceEntryInteractor.canSwipeToEnter.value,
shadeMode = shadeInteractor.shadeMode.value,
- isCustomizing = qsSceneAdapter.isCustomizing.value,
+ isCustomizing = qsSceneAdapter.isCustomizerShowing.value,
),
)
diff --git a/packages/SystemUI/src/com/android/systemui/slice/SliceViewManagerExt.kt b/packages/SystemUI/src/com/android/systemui/slice/SliceViewManagerExt.kt
index 384acc4..dd79425 100644
--- a/packages/SystemUI/src/com/android/systemui/slice/SliceViewManagerExt.kt
+++ b/packages/SystemUI/src/com/android/systemui/slice/SliceViewManagerExt.kt
@@ -28,6 +28,9 @@
* Returns updating [Slice] for a [sliceUri]. It's null when there is no slice available for the
* provided Uri. This can change overtime because of external changes (like device being
* connected/disconnected).
+ *
+ * The flow should be [kotlinx.coroutines.flow.flowOn] the main thread because [SliceViewManager]
+ * isn't thread-safe. An exception will be thrown otherwise.
*/
fun SliceViewManager.sliceForUri(sliceUri: Uri): Flow<Slice?> =
ConflatedCallbackFlow.conflatedCallbackFlow {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutListSearch.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutListSearch.java
index 78e108d..0d8030f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutListSearch.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutListSearch.java
@@ -97,7 +97,7 @@
public final class KeyboardShortcutListSearch {
private static final String TAG = KeyboardShortcutListSearch.class.getSimpleName();
private static final Object sLock = new Object();
- @VisibleForTesting static KeyboardShortcutListSearch sInstance;
+ @VisibleForTesting public static KeyboardShortcutListSearch sInstance;
private static int SHORTCUT_SYSTEM_INDEX = 0;
private static int SHORTCUT_INPUT_INDEX = 1;
@@ -136,7 +136,7 @@
};
private final Handler mHandler = new Handler(Looper.getMainLooper());
- @VisibleForTesting Context mContext;
+ @VisibleForTesting public Context mContext;
private final IPackageManager mPackageManager;
@VisibleForTesting BottomSheetDialog mKeyboardShortcutsBottomSheetDialog;
@@ -414,7 +414,7 @@
private boolean mImeShortcutsReceived;
@VisibleForTesting
- void showKeyboardShortcuts(int deviceId) {
+ public void showKeyboardShortcuts(int deviceId) {
retrieveKeyCharacterMap(deviceId);
mAppShortcutsReceived = false;
mImeShortcutsReceived = false;
@@ -502,7 +502,8 @@
return keyboardShortcutMultiMappingGroups;
}
- private void dismissKeyboardShortcuts() {
+ @VisibleForTesting
+ public void dismissKeyboardShortcuts() {
if (mKeyboardShortcutsBottomSheetDialog != null) {
mKeyboardShortcutsBottomSheetDialog.dismiss();
mKeyboardShortcutsBottomSheetDialog = null;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
index 90567d8..21f608e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
@@ -79,7 +79,7 @@
public final class KeyboardShortcuts {
private static final String TAG = KeyboardShortcuts.class.getSimpleName();
private static final Object sLock = new Object();
- @VisibleForTesting static KeyboardShortcuts sInstance;
+ @VisibleForTesting public static KeyboardShortcuts sInstance;
private WindowManager mWindowManager;
private final SparseArray<String> mSpecialCharacterNames = new SparseArray<>();
@@ -93,7 +93,7 @@
};
private final Handler mHandler = new Handler(Looper.getMainLooper());
- @VisibleForTesting Context mContext;
+ @VisibleForTesting public Context mContext;
private final IPackageManager mPackageManager;
private final OnClickListener mDialogCloseListener = new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
@@ -373,7 +373,7 @@
}
@VisibleForTesting
- void showKeyboardShortcuts(int deviceId) {
+ public void showKeyboardShortcuts(int deviceId) {
retrieveKeyCharacterMap(deviceId);
mReceivedAppShortcutGroups = null;
mReceivedImeShortcutGroups = null;
@@ -407,7 +407,8 @@
showKeyboardShortcutsDialog(shortcutGroups);
}
- private void dismissKeyboardShortcuts() {
+ @VisibleForTesting
+ public void dismissKeyboardShortcuts() {
if (mKeyboardShortcutsDialog != null) {
mKeyboardShortcutsDialog.dismiss();
mKeyboardShortcutsDialog = null;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutsReceiver.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutsReceiver.java
index 1cfb400..815f1fc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutsReceiver.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutsReceiver.java
@@ -15,6 +15,8 @@
*/
package com.android.systemui.statusbar;
+import static com.android.systemui.Flags.keyboardShortcutHelperRewrite;
+
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -25,21 +27,22 @@
import javax.inject.Inject;
-/**
- * Receiver for the Keyboard Shortcuts Helper.
- */
+/** Receiver for the Keyboard Shortcuts Helper. */
public class KeyboardShortcutsReceiver extends BroadcastReceiver {
- private boolean mIsShortcutListSearchEnabled;
+ private final FeatureFlags mFeatureFlags;
@Inject
public KeyboardShortcutsReceiver(FeatureFlags featureFlags) {
- mIsShortcutListSearchEnabled = featureFlags.isEnabled(Flags.SHORTCUT_LIST_SEARCH_LAYOUT);
+ mFeatureFlags = featureFlags;
}
@Override
public void onReceive(Context context, Intent intent) {
- if (mIsShortcutListSearchEnabled && Utilities.isLargeScreen(context)) {
+ if (keyboardShortcutHelperRewrite()) {
+ return;
+ }
+ if (isTabletLayoutFlagEnabled() && Utilities.isLargeScreen(context)) {
if (Intent.ACTION_SHOW_KEYBOARD_SHORTCUTS.equals(intent.getAction())) {
KeyboardShortcutListSearch.show(context, -1 /* deviceId unknown */);
} else if (Intent.ACTION_DISMISS_KEYBOARD_SHORTCUTS.equals(intent.getAction())) {
@@ -53,4 +56,8 @@
}
}
}
+
+ private boolean isTabletLayoutFlagEnabled() {
+ return mFeatureFlags.isEnabled(Flags.SHORTCUT_LIST_SEARCH_LAYOUT);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
index 222b070..14e14f4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
@@ -14,7 +14,6 @@
import androidx.annotation.VisibleForTesting
import com.android.systemui.Dumpable
import com.android.systemui.ExpandHelper
-import com.android.systemui.Flags.nsslFalsingFix
import com.android.systemui.Gefingerpoken
import com.android.systemui.biometrics.UdfpsKeyguardViewControllerLegacy
import com.android.systemui.classifier.Classifier
@@ -884,9 +883,7 @@
isDraggingDown = false
isTrackpadReverseScroll = false
shadeRepository.setLegacyLockscreenShadeTracking(false)
- if (nsslFalsingFix() || MigrateClocksToBlueprint.isEnabled) {
- return true
- }
+ return true
} else {
stopDragging()
return false
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
index 4d7dacd..d7d3732 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
@@ -387,11 +387,10 @@
Log.v(TAG, "DEBUG_MEDIA: Disconnecting from old controller: "
+ mMediaController.getPackageName());
}
- mBackgroundExecutor.execute(() -> {
- mMediaController.unregisterCallback(mMediaListener);
- mMediaController = null;
- });
+ // TODO(b/336612071): move to background thread
+ mMediaController.unregisterCallback(mMediaListener);
}
+ mMediaController = null;
}
public interface MediaListener {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
index 4f8c3caa..70632d5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
@@ -677,7 +677,9 @@
Scenes.Bouncer, StatusBarState.KEYGUARD,
Scenes.Communal, StatusBarState.KEYGUARD,
Scenes.Shade, StatusBarState.SHADE_LOCKED,
+ Scenes.NotificationsShade, StatusBarState.SHADE_LOCKED,
Scenes.QuickSettings, StatusBarState.SHADE_LOCKED,
+ Scenes.QuickSettingsShade, StatusBarState.SHADE_LOCKED,
Scenes.Gone, StatusBarState.SHADE
);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
index 61cdea1..6a38f8d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
@@ -38,6 +38,7 @@
import com.android.settingslib.Utils;
import com.android.systemui.Gefingerpoken;
import com.android.systemui.res.R;
+import com.android.systemui.shade.TouchLogger;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.notification.FakeShadowView;
import com.android.systemui.statusbar.notification.NotificationUtils;
@@ -745,6 +746,12 @@
}
}
+ @Override
+ public boolean dispatchTouchEvent(MotionEvent ev) {
+ return TouchLogger.logDispatchTouch(
+ getClass().getSimpleName(), ev, super.dispatchTouchEvent(ev));
+ }
+
/**
* SourceType which should be reset when this View is detached
* @param sourceType will be reset on View detached
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/ActivatableNotificationViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/ActivatableNotificationViewBinder.kt
index 9a54de1..2527af8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/ActivatableNotificationViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/ActivatableNotificationViewBinder.kt
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.notification.row.ui.viewbinder
+import android.util.Log
import android.view.MotionEvent
import android.view.View
import android.view.View.OnTouchListener
@@ -72,7 +73,6 @@
var isTouchEnabled = false
override fun onTouch(v: View, ev: MotionEvent): Boolean {
- val result = false
if (ev.action == MotionEvent.ACTION_UP) {
view.setLastActionUpTime(ev.eventTime)
}
@@ -82,13 +82,22 @@
}
if (ev.action == MotionEvent.ACTION_UP) {
// If this is a false tap, capture the even so it doesn't result in a click.
- return falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)
+ return falsingManager.isFalseTap(FalsingManager.LOW_PENALTY).also {
+ if (it) {
+ Log.d(v::class.simpleName ?: TAG, "capturing false tap")
+ }
+ }
}
- return result
+ return false
}
override fun onInterceptTouchEvent(ev: MotionEvent): Boolean = false
/** Use [onTouch] instead. */
override fun onTouchEvent(ev: MotionEvent): Boolean = false
+
+ companion object {
+ private const val TAG = "ActivatableNotificationViewBinder"
+ }
}
+
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 57504b2..773a6bf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -126,7 +126,6 @@
import com.android.systemui.statusbar.policy.SplitShadeStateController;
import com.android.systemui.util.Assert;
import com.android.systemui.util.ColorUtilKt;
-import com.android.systemui.util.Compile;
import com.android.systemui.util.DumpUtilsKt;
import com.google.errorprone.annotations.CompileTimeConstant;
@@ -156,7 +155,6 @@
public static final float BACKGROUND_ALPHA_DIMMED = 0.7f;
private static final String TAG = "StackScroller";
private static final boolean SPEW = Log.isLoggable(TAG, Log.VERBOSE);
- private static final boolean DEBUG_UPDATE_SIDE_PADDING = Compile.IS_DEBUG;
private boolean mShadeNeedsToClose = false;
@@ -933,11 +931,6 @@
+ " mSkinnyNotifsInLandscape=" + mSkinnyNotifsInLandscape;
mLastInitViewElapsedRealtime = SystemClock.elapsedRealtime();
- if (DEBUG_UPDATE_SIDE_PADDING) {
- Log.v(TAG, "initView @ elapsedRealtime " + mLastInitViewElapsedRealtime + ": "
- + mLastInitViewDumpString);
- }
-
mGapHeight = res.getDimensionPixelSize(R.dimen.notification_section_divider_height);
mStackScrollAlgorithm.initView(context);
mStateAnimator.initView(context);
@@ -967,12 +960,6 @@
+ " orientation=" + orientation;
mLastUpdateSidePaddingElapsedRealtime = SystemClock.elapsedRealtime();
- if (DEBUG_UPDATE_SIDE_PADDING) {
- Log.v(TAG,
- "updateSidePadding @ elapsedRealtime " + mLastUpdateSidePaddingElapsedRealtime
- + ": " + mLastUpdateSidePaddingDumpString);
- }
-
if (viewWidth == 0) {
Log.e(TAG, "updateSidePadding: viewWidth is zero");
mSidePaddings = mMinimumPaddings;
@@ -1146,12 +1133,18 @@
}
}
+ @NonNull
@Override
public View asView() {
return this;
}
@Override
+ public void setMaxAlpha(float alpha) {
+ mController.setMaxAlphaFromView(alpha);
+ }
+
+ @Override
public void setScrolledToTop(boolean scrolledToTop) {
mScrollViewFields.setScrolledToTop(scrolledToTop);
}
@@ -1179,6 +1172,11 @@
}
@Override
+ public void setCurrentGestureOverscrollConsumer(@Nullable Consumer<Boolean> consumer) {
+ mScrollViewFields.setCurrentGestureOverscrollConsumer(consumer);
+ }
+
+ @Override
public void setStackHeightConsumer(@Nullable Consumer<Float> consumer) {
mScrollViewFields.setStackHeightConsumer(consumer);
}
@@ -3397,6 +3395,8 @@
boolean isUpOrCancel = action == ACTION_UP || action == ACTION_CANCEL;
if (mSendingTouchesToSceneFramework) {
mController.sendTouchToSceneFramework(ev);
+ mScrollViewFields.sendCurrentGestureOverscroll(
+ getExpandedInThisMotion() && !isUpOrCancel);
} else if (!isUpOrCancel) {
// if this is the first touch being sent to the scene framework,
// convert it into a synthetic DOWN event.
@@ -3404,6 +3404,7 @@
MotionEvent downEvent = MotionEvent.obtain(ev);
downEvent.setAction(MotionEvent.ACTION_DOWN);
mController.sendTouchToSceneFramework(downEvent);
+ mScrollViewFields.sendCurrentGestureOverscroll(getExpandedInThisMotion());
downEvent.recycle();
}
@@ -3422,6 +3423,14 @@
downEvent.recycle();
}
+ // Only when scene container is enabled, mark that we are being dragged so that we start
+ // dispatching the rest of the gesture to scene container.
+ void startOverscrollAfterExpanding() {
+ SceneContainerFlag.isUnexpectedlyInLegacyMode();
+ getExpandHelper().finishExpanding();
+ setIsBeingDragged(true);
+ }
+
@Override
public boolean onGenericMotionEvent(MotionEvent event) {
if (!isScrollingEnabled()
@@ -5539,6 +5548,11 @@
return mExpandingNotification;
}
+ @VisibleForTesting
+ void setExpandingNotification(boolean isExpanding) {
+ mExpandingNotification = isExpanding;
+ }
+
boolean getDisallowScrollingInThisMotion() {
return mDisallowScrollingInThisMotion;
}
@@ -5551,6 +5565,11 @@
return mExpandedInThisMotion;
}
+ @VisibleForTesting
+ void setExpandedInThisMotion(boolean expandedInThisMotion) {
+ mExpandedInThisMotion = expandedInThisMotion;
+ }
+
boolean getDisallowDismissInThisMotion() {
return mDisallowDismissInThisMotion;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index 9ed5ac9..c1c63cd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -23,7 +23,6 @@
import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_SCROLL_FLING;
import static com.android.server.notification.Flags.screenshareNotificationHiding;
import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
-import static com.android.systemui.Flags.nsslFalsingFix;
import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.OnEmptySpaceClickListener;
import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.OnOverscrollTopChangedListener;
@@ -206,6 +205,7 @@
private final SeenNotificationsInteractor mSeenNotificationsInteractor;
private final KeyguardTransitionRepository mKeyguardTransitionRepo;
private NotificationStackScrollLayout mView;
+ private TouchHandler mTouchHandler;
private NotificationSwipeHelper mSwipeHelper;
@Nullable
private Boolean mHistoryEnabled;
@@ -356,6 +356,7 @@
private float mMaxAlphaForKeyguard = 1.0f;
private String mMaxAlphaForKeyguardSource = "constructor";
private float mMaxAlphaForUnhide = 1.0f;
+ private float mMaxAlphaFromView = 1.0f;
/**
* Maximum alpha when to and from or sitting idle on the glanceable hub. Will be 1.0f when the
@@ -806,7 +807,8 @@
mView.setStackStateLogger(mStackStateLogger);
mView.setController(this);
mView.setLogger(mLogger);
- mView.setTouchHandler(new TouchHandler());
+ mTouchHandler = new TouchHandler();
+ mView.setTouchHandler(mTouchHandler);
mView.setResetUserExpandedStatesRunnable(mNotificationsController::resetUserExpandedStates);
mView.setActivityStarter(mActivityStarter);
mView.setClearAllAnimationListener(this::onAnimationEnd);
@@ -1317,9 +1319,14 @@
updateAlpha();
}
+ void setMaxAlphaFromView(float alpha) {
+ mMaxAlphaFromView = alpha;
+ updateAlpha();
+ }
+
private void updateAlpha() {
if (mView != null) {
- mView.setAlpha(Math.min(mMaxAlphaForKeyguard,
+ mView.setAlpha(Math.min(Math.min(mMaxAlphaFromView, mMaxAlphaForKeyguard),
Math.min(mMaxAlphaForUnhide, mMaxAlphaForGlanceableHub)));
}
}
@@ -1787,8 +1794,14 @@
}
}
+ @VisibleForTesting
+ TouchHandler getTouchHandler() {
+ return mTouchHandler;
+ }
+
@Override
public void dump(@NonNull PrintWriter pw, @NonNull String[] args) {
+ pw.println("mMaxAlphaFromView=" + mMaxAlphaFromView);
pw.println("mMaxAlphaForUnhide=" + mMaxAlphaForUnhide);
pw.println("mMaxAlphaForGlanceableHub=" + mMaxAlphaForGlanceableHub);
pw.println("mMaxAlphaForKeyguard=" + mMaxAlphaForKeyguard);
@@ -2036,37 +2049,30 @@
expandingNotification = mView.isExpandingNotification();
if (mView.getExpandedInThisMotion() && !expandingNotification && wasExpandingBefore
&& !mView.getDisallowScrollingInThisMotion()) {
- mView.dispatchDownEventToScroller(ev);
+ // We need to dispatch the overscroll differently when Scene Container is on,
+ // since NSSL no longer controls its own scroll.
+ if (SceneContainerFlag.isEnabled() && !isCancelOrUp) {
+ mView.startOverscrollAfterExpanding();
+ return true;
+ } else {
+ mView.dispatchDownEventToScroller(ev);
+ }
}
}
boolean horizontalSwipeWantsIt = false;
boolean scrollerWantsIt = false;
- if (nsslFalsingFix() || MigrateClocksToBlueprint.isEnabled()) {
- // Reverse the order relative to the else statement. onScrollTouch will reset on an
- // UP event, causing horizontalSwipeWantsIt to be set to true on vertical swipes.
- if (mLongPressedView == null && !mView.isBeingDragged()
- && !expandingNotification
- && !mView.getExpandedInThisMotion()
- && !onlyScrollingInThisMotion
- && !mView.getDisallowDismissInThisMotion()) {
- horizontalSwipeWantsIt = mSwipeHelper.onTouchEvent(ev);
- }
- if (mLongPressedView == null && mView.isExpanded() && !mSwipeHelper.isSwiping()
- && !expandingNotification && !mView.getDisallowScrollingInThisMotion()) {
- scrollerWantsIt = mView.onScrollTouch(ev);
- }
- } else {
- if (mLongPressedView == null && mView.isExpanded() && !mSwipeHelper.isSwiping()
- && !expandingNotification && !mView.getDisallowScrollingInThisMotion()) {
- scrollerWantsIt = mView.onScrollTouch(ev);
- }
- if (mLongPressedView == null && !mView.isBeingDragged()
- && !expandingNotification
- && !mView.getExpandedInThisMotion()
- && !onlyScrollingInThisMotion
- && !mView.getDisallowDismissInThisMotion()) {
- horizontalSwipeWantsIt = mSwipeHelper.onTouchEvent(ev);
- }
+ // NOTE: the order of these is important. If reversed, onScrollTouch will reset on an
+ // UP event, causing horizontalSwipeWantsIt to be set to true on vertical swipes.
+ if (mLongPressedView == null && !mView.isBeingDragged()
+ && !expandingNotification
+ && !mView.getExpandedInThisMotion()
+ && !onlyScrollingInThisMotion
+ && !mView.getDisallowDismissInThisMotion()) {
+ horizontalSwipeWantsIt = mSwipeHelper.onTouchEvent(ev);
+ }
+ if (mLongPressedView == null && mView.isExpanded() && !mSwipeHelper.isSwiping()
+ && !expandingNotification && !mView.getDisallowScrollingInThisMotion()) {
+ scrollerWantsIt = mView.onScrollTouch(ev);
}
// Check if we need to clear any snooze leavebehinds
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ScrollViewFields.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ScrollViewFields.kt
index edac5ed..a3827c1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ScrollViewFields.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ScrollViewFields.kt
@@ -51,6 +51,11 @@
*/
var syntheticScrollConsumer: Consumer<Float>? = null
/**
+ * When a gesture is consumed internally by NSSL but needs to be handled by other elements (such
+ * as the notif scrim) as overscroll, we can notify the placeholder through here.
+ */
+ var currentGestureOverscrollConsumer: Consumer<Boolean>? = null
+ /**
* Any time the stack height is recalculated, it should be updated here to be used by the
* placeholder
*/
@@ -64,6 +69,9 @@
/** send the [syntheticScroll] to the [syntheticScrollConsumer], if present. */
fun sendSyntheticScroll(syntheticScroll: Float) =
syntheticScrollConsumer?.accept(syntheticScroll)
+ /** send [isCurrentGestureOverscroll] to the [currentGestureOverscrollConsumer], if present. */
+ fun sendCurrentGestureOverscroll(isCurrentGestureOverscroll: Boolean) =
+ currentGestureOverscrollConsumer?.accept(isCurrentGestureOverscroll)
/** send the [stackHeight] to the [stackHeightConsumer], if present. */
fun sendStackHeight(stackHeight: Float) = stackHeightConsumer?.accept(stackHeight)
/** send the [headsUpHeight] to the [headsUpHeightConsumer], if present. */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
index e980794..d0cebae 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -169,6 +169,14 @@
}
}
+ // On the final call to {@link #resetViewState}, the alpha is set back to 1f but
+ // ambientState.isExpansionChanging() is now false. This causes a flicker on the
+ // EmptyShadeView after the shade is collapsed. Make sure the empty shade view
+ // isn't visible unless the shade is expanded.
+ if (view instanceof EmptyShadeView && ambientState.getExpansionFraction() == 0f) {
+ viewState.setAlpha(0f);
+ }
+
// For EmptyShadeView if on keyguard, we need to control the alpha to create
// a nice transition when the user is dragging down the notification panel.
if (view instanceof EmptyShadeView && ambientState.isOnKeyguard()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/data/repository/NotificationPlaceholderRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/data/repository/NotificationPlaceholderRepository.kt
index b047379..dacafc4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/data/repository/NotificationPlaceholderRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/data/repository/NotificationPlaceholderRepository.kt
@@ -27,6 +27,10 @@
*/
@SysUISingleton
class NotificationPlaceholderRepository @Inject constructor() {
+
+ /** The alpha of the shade in order to show brightness. */
+ val alphaForBrightnessMirror = MutableStateFlow(1f)
+
/**
* The bounds of the notification shade scrim / container in the current scene.
*
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/data/repository/NotificationViewHeightRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/data/repository/NotificationViewHeightRepository.kt
index 8a9da69..920c9c2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/data/repository/NotificationViewHeightRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/data/repository/NotificationViewHeightRepository.kt
@@ -43,4 +43,10 @@
* necessary to scroll up to keep expanding the notification.
*/
val syntheticScroll = MutableStateFlow(0f)
+
+ /**
+ * Whether the current touch gesture is overscroll. If true, it means the NSSL has already
+ * consumed part of the gesture.
+ */
+ val isCurrentGestureOverscroll = MutableStateFlow(false)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackAppearanceInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackAppearanceInteractor.kt
index a5b4f5f..b94da38 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackAppearanceInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackAppearanceInteractor.kt
@@ -75,6 +75,10 @@
/** The height in px of the contents of the HUN. */
val headsUpHeight: StateFlow<Float> = viewHeightRepository.headsUpHeight.asStateFlow()
+ /** The alpha of the Notification Stack for the brightness mirror */
+ val alphaForBrightnessMirror: StateFlow<Float> =
+ placeholderRepository.alphaForBrightnessMirror.asStateFlow()
+
/** The y-coordinate in px of top of the contents of the notification stack. */
val stackTop: StateFlow<Float> = placeholderRepository.stackTop.asStateFlow()
@@ -101,6 +105,18 @@
*/
val syntheticScroll: Flow<Float> = viewHeightRepository.syntheticScroll.asStateFlow()
+ /**
+ * Whether the current touch gesture is overscroll. If true, it means the NSSL has already
+ * consumed part of the gesture.
+ */
+ val isCurrentGestureOverscroll: Flow<Boolean> =
+ viewHeightRepository.isCurrentGestureOverscroll.asStateFlow()
+
+ /** Sets the alpha to apply to the NSSL for the brightness mirror */
+ fun setAlphaForBrightnessMirror(alpha: Float) {
+ placeholderRepository.alphaForBrightnessMirror.value = alpha
+ }
+
/** Sets the position of the notification stack in the current scene. */
fun setShadeScrimBounds(bounds: ShadeScrimBounds?) {
check(bounds == null || bounds.top <= bounds.bottom) { "Invalid bounds: $bounds" }
@@ -137,6 +153,11 @@
viewHeightRepository.syntheticScroll.value = delta
}
+ /** Sets whether the current touch gesture is overscroll. */
+ fun setCurrentGestureOverscroll(isOverscroll: Boolean) {
+ viewHeightRepository.isCurrentGestureOverscroll.value = isOverscroll
+ }
+
fun setConstrainedAvailableSpace(height: Int) {
placeholderRepository.constrainedAvailableSpace.value = height
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/SharedNotificationContainerInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/SharedNotificationContainerInteractor.kt
index 20e8cac..9b21fa9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/SharedNotificationContainerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/SharedNotificationContainerInteractor.kt
@@ -29,11 +29,10 @@
import dagger.Lazy
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onStart
@@ -54,9 +53,9 @@
private val _topPosition = MutableStateFlow(0f)
val topPosition = _topPosition.asStateFlow()
- private val _notificationStackChanged = MutableSharedFlow<Unit>(extraBufferCapacity = 1)
+ private val _notificationStackChanged = MutableStateFlow(0L)
/** An internal modification was made to notifications */
- val notificationStackChanged = _notificationStackChanged.asSharedFlow()
+ val notificationStackChanged = _notificationStackChanged.debounce(20L)
val configurationBasedDimensions: Flow<ConfigurationBasedDimensions> =
configurationRepository.onAnyConfigurationChange
@@ -113,7 +112,7 @@
/** An internal modification was made to notifications */
fun notificationStackChanged() {
- _notificationStackChanged.tryEmit(Unit)
+ _notificationStackChanged.value = _notificationStackChanged.value + 1
}
data class ConfigurationBasedDimensions(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/view/NotificationScrollView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/view/NotificationScrollView.kt
index f356578..2c88845 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/view/NotificationScrollView.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/view/NotificationScrollView.kt
@@ -31,6 +31,9 @@
*/
fun asView(): View
+ /** Max alpha for this view */
+ fun setMaxAlpha(alpha: Float)
+
/** Set the clipping bounds used when drawing */
fun setScrimClippingShape(shape: ShadeScrimShape?)
@@ -48,6 +51,8 @@
/** Set a consumer for synthetic scroll events */
fun setSyntheticScrollConsumer(consumer: Consumer<Float>?)
+ /** Set a consumer for current gesture overscroll events */
+ fun setCurrentGestureOverscrollConsumer(consumer: Consumer<Boolean>?)
/** Set a consumer for stack height changed events */
fun setStackHeightConsumer(consumer: Consumer<Float>?)
/** Set a consumer for heads up height changed events */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationScrollViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationScrollViewBinder.kt
index 2f9c2f0..26f7ad7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationScrollViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationScrollViewBinder.kt
@@ -78,20 +78,23 @@
.collect { view.setScrimClippingShape(it) }
}
+ launch { viewModel.maxAlpha.collect { view.setMaxAlpha(it) } }
launch { viewModel.stackTop.collect { view.setStackTop(it) } }
launch { viewModel.stackBottom.collect { view.setStackBottom(it) } }
launch { viewModel.scrolledToTop.collect { view.setScrolledToTop(it) } }
launch { viewModel.headsUpTop.collect { view.setHeadsUpTop(it) } }
- launch { viewModel.expandFraction.collect { view.setExpandFraction(it) } }
+ launch { viewModel.expandFraction.collect { view.setExpandFraction(it.coerceIn(0f, 1f)) } }
launch { viewModel.isScrollable.collect { view.setScrollingEnabled(it) } }
launch { viewModel.isDozing.collect { isDozing -> view.setDozing(isDozing) } }
launchAndDispose {
view.setSyntheticScrollConsumer(viewModel.syntheticScrollConsumer)
+ view.setCurrentGestureOverscrollConsumer(viewModel.currentGestureOverscrollConsumer)
view.setStackHeightConsumer(viewModel.stackHeightConsumer)
view.setHeadsUpHeightConsumer(viewModel.headsUpHeightConsumer)
DisposableHandle {
view.setSyntheticScrollConsumer(null)
+ view.setCurrentGestureOverscrollConsumer(null)
view.setStackHeightConsumer(null)
view.setHeadsUpHeightConsumer(null)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModel.kt
index 7aeff71..b2184db 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModel.kt
@@ -32,12 +32,12 @@
import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationTransitionThresholds.EXPANSION_FOR_MAX_SCRIM_ALPHA
import com.android.systemui.util.kotlin.FlowDumperImpl
import dagger.Lazy
+import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
-import javax.inject.Inject
/** ViewModel which represents the state of the NSSL/Controller in the world of flexiglass */
@SysUISingleton
@@ -65,7 +65,7 @@
) { shadeExpansion, qsExpansion, transitionState ->
when (transitionState) {
is ObservableTransitionState.Idle -> {
- if (transitionState.scene == Scenes.Lockscreen) {
+ if (transitionState.currentScene == Scenes.Lockscreen) {
1f
} else {
shadeExpansion
@@ -122,6 +122,14 @@
}
.dumpWhileCollecting("shadeScrimShape")
+ /**
+ * Max alpha to apply directly to the view based on the compose placeholder.
+ *
+ * TODO(b/338590620): Migrate alphas from [SharedNotificationContainerViewModel] into this flow
+ */
+ val maxAlpha: Flow<Float> =
+ stackAppearanceInteractor.alphaForBrightnessMirror.dumpValue("maxAlpha")
+
/** The y-coordinate in px of top of the contents of the notification stack. */
val stackTop: Flow<Float> = stackAppearanceInteractor.stackTop.dumpValue("stackTop")
/** The y-coordinate in px of bottom of the contents of the notification stack. */
@@ -137,6 +145,12 @@
/** Receives the amount (px) that the stack should scroll due to internal expansion. */
val syntheticScrollConsumer: (Float) -> Unit = stackAppearanceInteractor::setSyntheticScroll
+ /**
+ * Receives whether the current touch gesture is overscroll as it has already been consumed by
+ * the stack.
+ */
+ val currentGestureOverscrollConsumer: (Boolean) -> Unit =
+ stackAppearanceInteractor::setCurrentGestureOverscroll
/** Receives the height of the contents of the notification stack. */
val stackHeightConsumer: (Float) -> Unit = stackAppearanceInteractor::setStackHeight
/** Receives the height of the heads up notification. */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModel.kt
index bf3b2c9..11eaf54 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModel.kt
@@ -78,6 +78,11 @@
interactor.setHeadsUpTop(headsUpTop)
}
+ /** Sets the content alpha for the current state of the brightness mirror */
+ fun setAlphaForBrightnessMirror(alpha: Float) {
+ interactor.setAlphaForBrightnessMirror(alpha)
+ }
+
/** Corner rounding of the stack */
val shadeScrimRounding: Flow<ShadeScrimRounding> =
interactor.shadeScrimRounding.dumpWhileCollecting("shadeScrimRounding")
@@ -106,6 +111,13 @@
val syntheticScroll: Flow<Float> =
interactor.syntheticScroll.dumpWhileCollecting("syntheticScroll")
+ /**
+ * Whether the current touch gesture is overscroll. If true, it means the NSSL has already
+ * consumed part of the gesture.
+ */
+ val isCurrentGestureOverscroll: Flow<Boolean> =
+ interactor.isCurrentGestureOverscroll.dumpWhileCollecting("isCurrentGestureOverScroll")
+
/** Sets whether the notification stack is scrolled to the top. */
fun setScrolledToTop(scrolledToTop: Boolean) {
interactor.setScrolledToTop(scrolledToTop)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt
index ac4bd09..0ba7b3c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt
@@ -68,8 +68,8 @@
import com.android.systemui.statusbar.notification.stack.domain.interactor.NotificationStackAppearanceInteractor
import com.android.systemui.statusbar.notification.stack.domain.interactor.SharedNotificationContainerInteractor
import com.android.systemui.unfold.domain.interactor.UnfoldTransitionInteractor
-import com.android.systemui.util.kotlin.BooleanFlowOperators.and
-import com.android.systemui.util.kotlin.BooleanFlowOperators.or
+import com.android.systemui.util.kotlin.BooleanFlowOperators.allOf
+import com.android.systemui.util.kotlin.BooleanFlowOperators.anyOf
import com.android.systemui.util.kotlin.FlowDumperImpl
import com.android.systemui.util.kotlin.Utils.Companion.sample as sampleCombine
import javax.inject.Inject
@@ -246,7 +246,7 @@
keyguardTransitionInteractor.finishedKeyguardState.map { state ->
state == GLANCEABLE_HUB
},
- or(
+ anyOf(
keyguardTransitionInteractor.isInTransitionToState(GLANCEABLE_HUB),
keyguardTransitionInteractor.isInTransitionFromState(GLANCEABLE_HUB),
),
@@ -424,14 +424,14 @@
while (currentCoroutineContext().isActive) {
emit(false)
// Ensure states are inactive to start
- and(
+ allOf(
*toFlowArray(statesForHiddenKeyguard) { state ->
keyguardTransitionInteractor.transitionValue(state).map { it == 0f }
}
)
.first { it }
// Wait for a qualifying transition to begin
- or(
+ anyOf(
*toFlowArray(statesForHiddenKeyguard) { state ->
keyguardTransitionInteractor
.transitionStepsToState(state)
@@ -446,7 +446,7 @@
// it is considered safe to reset alpha to 1f for HUNs.
combine(
keyguardInteractor.statusBarState,
- and(
+ allOf(
*toFlowArray(statesForHiddenKeyguard) { state ->
keyguardTransitionInteractor.transitionValue(state).map {
it == 0f
@@ -636,7 +636,7 @@
showUnlimitedNotifications,
shadeInteractor.isUserInteracting,
availableHeight,
- interactor.notificationStackChanged.onStart { emit(Unit) },
+ interactor.notificationStackChanged,
interactor.useExtraShelfSpace,
) { flows ->
val showLimitedNotifications = flows[0] as Boolean
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
index 79e6a0a..f83aed8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -52,6 +52,7 @@
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.keyguard.domain.interactor.BiometricUnlockInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
+import com.android.systemui.keyguard.shared.model.BiometricUnlockSource;
import com.android.systemui.keyguard.shared.model.KeyguardState;
import com.android.systemui.keyguard.shared.model.TransitionStep;
import com.android.systemui.log.SessionTracker;
@@ -334,7 +335,7 @@
@VisibleForTesting
protected void consumeTransitionStepOnStartedKeyguardState(TransitionStep transitionStep) {
if (transitionStep.getFrom() == KeyguardState.GONE) {
- mBiometricUnlockInteractor.setBiometricUnlockState(MODE_NONE);
+ mBiometricUnlockInteractor.setBiometricUnlockState(MODE_NONE, null);
}
}
@@ -409,7 +410,10 @@
Trace.endSection();
return;
}
- startWakeAndUnlock(MODE_SHOW_BOUNCER);
+ startWakeAndUnlock(
+ MODE_SHOW_BOUNCER,
+ BiometricUnlockSource.Companion.fromBiometricSourceType(biometricSourceType)
+ );
}
@Override
@@ -456,10 +460,19 @@
|| mode == MODE_WAKE_AND_UNLOCK_FROM_DREAM || mode == MODE_DISMISS_BOUNCER) {
onBiometricUnlockedWithKeyguardDismissal(biometricSourceType);
}
- startWakeAndUnlock(mode);
+ startWakeAndUnlock(
+ mode,
+ BiometricUnlockSource.Companion.fromBiometricSourceType(biometricSourceType)
+ );
}
- public void startWakeAndUnlock(@WakeAndUnlockMode int mode) {
+ /**
+ * Wake and unlock the device in response to successful authentication using biometrics.
+ */
+ public void startWakeAndUnlock(
+ @WakeAndUnlockMode int mode,
+ BiometricUnlockSource biometricUnlockSource
+ ) {
mLogger.logStartWakeAndUnlock(mode);
boolean wasDeviceInteractive = mUpdateMonitor.isDeviceInteractive();
mMode = mode;
@@ -532,15 +545,18 @@
case MODE_NONE:
break;
}
- onModeChanged(mMode);
+ onModeChanged(mMode, biometricUnlockSource);
Trace.endSection();
}
- private void onModeChanged(@WakeAndUnlockMode int mode) {
+ private void onModeChanged(
+ @WakeAndUnlockMode int mode,
+ BiometricUnlockSource biometricUnlockSource
+ ) {
for (BiometricUnlockEventsListener listener : mBiometricUnlockEventsListeners) {
listener.onModeChanged(mode);
}
- mBiometricUnlockInteractor.setBiometricUnlockState(mode);
+ mBiometricUnlockInteractor.setBiometricUnlockState(mode, biometricUnlockSource);
}
private void onBiometricUnlockedWithKeyguardDismissal(BiometricSourceType biometricSourceType) {
@@ -719,7 +735,10 @@
final boolean screenOff = !mUpdateMonitor.isDeviceInteractive();
if (!mVibratorHelper.hasVibrator() && screenOff) {
mLogger.d("wakeup device on authentication failure (device doesn't have a vibrator)");
- startWakeAndUnlock(MODE_ONLY_WAKE);
+ startWakeAndUnlock(
+ MODE_ONLY_WAKE,
+ BiometricUnlockSource.Companion.fromBiometricSourceType(biometricSourceType)
+ );
} else if (biometricSourceType == BiometricSourceType.FINGERPRINT
&& mUpdateMonitor.isUdfpsSupported()) {
long currUptimeMillis = mSystemClock.uptimeMillis();
@@ -732,7 +751,10 @@
if (mNumConsecutiveFpFailures >= UDFPS_ATTEMPTS_BEFORE_SHOW_BOUNCER) {
mLogger.logUdfpsAttemptThresholdMet(mNumConsecutiveFpFailures);
- startWakeAndUnlock(MODE_SHOW_BOUNCER);
+ startWakeAndUnlock(
+ MODE_SHOW_BOUNCER,
+ BiometricUnlockSource.Companion.fromBiometricSourceType(biometricSourceType)
+ );
UI_EVENT_LOGGER.log(BiometricUiEvent.BIOMETRIC_BOUNCER_SHOWN, getSessionId());
mNumConsecutiveFpFailures = 0;
}
@@ -755,7 +777,10 @@
|| msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT);
if (fingerprintLockout) {
mLogger.d("fingerprint locked out");
- startWakeAndUnlock(MODE_SHOW_BOUNCER);
+ startWakeAndUnlock(
+ MODE_SHOW_BOUNCER,
+ BiometricUnlockSource.Companion.fromBiometricSourceType(biometricSourceType)
+ );
UI_EVENT_LOGGER.log(BiometricUiEvent.BIOMETRIC_BOUNCER_SHOWN, getSessionId());
}
@@ -897,7 +922,8 @@
public interface BiometricUnlockEventsListener {
/** Called when {@code mMode} is reset to {@link #MODE_NONE}. */
default void onResetMode() {}
- /** Called when {@code mMode} has changed in {@link #startWakeAndUnlock(int)}. */
+ /** Called when {@code mMode} has changed in
+ * {@link #startWakeAndUnlock(int, BiometricUnlockSource)}. */
default void onModeChanged(@WakeAndUnlockMode int mode) {}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
index 7630d43..be6bef7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -26,10 +26,12 @@
import static androidx.lifecycle.Lifecycle.State.RESUMED;
import static com.android.systemui.Dependency.TIME_TICK_HANDLER_NAME;
+import static com.android.systemui.Flags.keyboardShortcutHelperRewrite;
import static com.android.systemui.Flags.lightRevealMigration;
import static com.android.systemui.Flags.newAodTransition;
import static com.android.systemui.Flags.truncatedStatusBarIconsFix;
import static com.android.systemui.charging.WirelessChargingAnimation.UNKNOWN_BATTERY_LEVEL;
+import static com.android.systemui.flags.Flags.SHORTCUT_LIST_SEARCH_LAYOUT;
import static com.android.systemui.statusbar.NotificationLockscreenUserManager.PERMISSION_SELF;
import static com.android.systemui.statusbar.StatusBarState.SHADE;
@@ -289,7 +291,6 @@
private CentralSurfacesCommandQueueCallbacks mCommandQueueCallbacks;
private float mTransitionToFullShadeProgress = 0f;
private final NotificationListContainer mNotifListContainer;
- private final boolean mIsShortcutListSearchEnabled;
private final KeyguardStateController.Callback mKeyguardStateControllerCallback =
new KeyguardStateController.Callback() {
@@ -789,7 +790,6 @@
mStatusBarSignalPolicy = statusBarSignalPolicy;
mStatusBarHideIconsForBouncerManager = statusBarHideIconsForBouncerManager;
mFeatureFlags = featureFlags;
- mIsShortcutListSearchEnabled = featureFlags.isEnabled(Flags.SHORTCUT_LIST_SEARCH_LAYOUT);
mKeyguardUnlockAnimationController = keyguardUnlockAnimationController;
mMainExecutor = delayableExecutor;
mMessageRouter = messageRouter;
@@ -820,10 +820,13 @@
// TODO(b/190746471): Find a better home for this.
DateTimeView.setReceiverHandler(timeTickHandler);
- mMessageRouter.subscribeTo(KeyboardShortcutsMessage.class,
- data -> toggleKeyboardShortcuts(data.mDeviceId));
- mMessageRouter.subscribeTo(MSG_DISMISS_KEYBOARD_SHORTCUTS_MENU,
- id -> dismissKeyboardShortcuts());
+ if (!keyboardShortcutHelperRewrite()) {
+ mMessageRouter.subscribeTo(
+ KeyboardShortcutsMessage.class,
+ data -> toggleKeyboardShortcuts(data.mDeviceId));
+ mMessageRouter.subscribeTo(
+ MSG_DISMISS_KEYBOARD_SHORTCUTS_MENU, id -> dismissKeyboardShortcuts());
+ }
mMessageRouter.subscribeTo(AnimateExpandSettingsPanelMessage.class,
data -> mCommandQueueCallbacks.animateExpandSettingsPanel(data.mSubpanel));
mMessageRouter.subscribeTo(MSG_LAUNCH_TRANSITION_TIMEOUT,
@@ -1872,10 +1875,12 @@
String action = intent.getAction();
String reason = intent.getStringExtra(SYSTEM_DIALOG_REASON_KEY);
if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) {
- if (mIsShortcutListSearchEnabled && Utilities.isLargeScreen(mContext)) {
- KeyboardShortcutListSearch.dismiss();
- } else {
- KeyboardShortcuts.dismiss();
+ if (!keyboardShortcutHelperRewrite()) {
+ if (shouldUseTabletKeyboardShortcuts()) {
+ KeyboardShortcutListSearch.dismiss();
+ } else {
+ KeyboardShortcuts.dismiss();
+ }
}
mRemoteInputManager.closeRemoteInputs();
if (mLockscreenUserManager.isCurrentProfile(getSendingUserId())) {
@@ -2345,6 +2350,7 @@
} else if (mState == StatusBarState.KEYGUARD
&& !mStatusBarKeyguardViewManager.primaryBouncerIsOrWillBeShowing()
&& mStatusBarKeyguardViewManager.isSecure()) {
+ Log.d(TAG, "showBouncerOrLockScreenIfKeyguard, showingBouncer");
mStatusBarKeyguardViewManager.showBouncer(true /* scrimmed */);
}
}
@@ -2945,7 +2951,7 @@
}
protected void toggleKeyboardShortcuts(int deviceId) {
- if (mIsShortcutListSearchEnabled && Utilities.isLargeScreen(mContext)) {
+ if (shouldUseTabletKeyboardShortcuts()) {
KeyboardShortcutListSearch.toggle(mContext, deviceId);
} else {
KeyboardShortcuts.toggle(mContext, deviceId);
@@ -2953,13 +2959,18 @@
}
protected void dismissKeyboardShortcuts() {
- if (mIsShortcutListSearchEnabled && Utilities.isLargeScreen(mContext)) {
+ if (shouldUseTabletKeyboardShortcuts()) {
KeyboardShortcutListSearch.dismiss();
} else {
KeyboardShortcuts.dismiss();
}
}
+ private boolean shouldUseTabletKeyboardShortcuts() {
+ return mFeatureFlags.isEnabled(SHORTCUT_LIST_SEARCH_LAYOUT)
+ && Utilities.isLargeScreen(mContext);
+ }
+
private void clearNotificationEffects() {
try {
mBarService.clearNotificationEffects();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt
index dea9416..2e1ab38 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt
@@ -59,7 +59,10 @@
}
override fun notifyThemeChanged() {
- val listeners = ArrayList(listeners)
+ // Avoid concurrent modification exception
+ val listeners = synchronized(this.listeners) {
+ ArrayList(this.listeners)
+ }
listeners.filterForEach({ this.listeners.contains(it) }) {
it.onThemeChanged()
@@ -68,8 +71,9 @@
override fun onConfigurationChanged(newConfig: Configuration) {
// Avoid concurrent modification exception
- val listeners = ArrayList(listeners)
-
+ val listeners = synchronized(this.listeners) {
+ ArrayList(this.listeners)
+ }
listeners.filterForEach({ this.listeners.contains(it) }) {
it.onConfigChanged(newConfig)
}
@@ -148,12 +152,16 @@
}
override fun addCallback(listener: ConfigurationListener) {
- listeners.add(listener)
+ synchronized(listeners) {
+ listeners.add(listener)
+ }
listener.onDensityOrFontScaleChanged()
}
override fun removeCallback(listener: ConfigurationListener) {
- listeners.remove(listener)
+ synchronized(listeners) {
+ listeners.remove(listener)
+ }
}
override fun isLayoutRtl(): Boolean {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
index 5deb08a7..cff46ab 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
@@ -37,6 +37,7 @@
import com.android.systemui.statusbar.pipeline.mobile.ui.MobileViewLogger;
import com.android.systemui.statusbar.pipeline.mobile.ui.view.ModernStatusBarMobileView;
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconsViewModel;
+import com.android.systemui.statusbar.pipeline.shared.ui.view.ModernStatusBarView;
import com.android.systemui.statusbar.pipeline.wifi.ui.view.ModernStatusBarWifiView;
import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.LocationBasedWifiViewModel;
@@ -277,6 +278,15 @@
addView(view, viewIndex, createLayoutParams());
}
+ /** Adds a bindable icon to the demo mode view. */
+ public void addBindableIcon(StatusBarIconHolder.BindableIconHolder holder) {
+ // This doesn't do any correct ordering, and also doesn't check if we already have an
+ // existing icon for the slot. But since we hope to remove this class soon, we won't spend
+ // the time adding that logic.
+ ModernStatusBarView view = holder.getInitializer().createAndBind(mContext);
+ addView(view, createLayoutParams());
+ }
+
public void onRemoveIcon(StatusIconDisplayable view) {
if (view.getSlot().equals("wifi")) {
if (view instanceof ModernStatusBarWifiView) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
index 3cdf68f..84e6018 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
@@ -41,6 +41,7 @@
import android.widget.RelativeLayout;
import android.widget.TextView;
+import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import com.android.settingslib.Utils;
@@ -291,7 +292,16 @@
}
private boolean updateLayoutConsideringCutout(StatusBarContentInsetsProvider insetsProvider) {
- mDisplayCutout = getRootWindowInsets().getDisplayCutout();
+ return setDisplayCutout(
+ getRootWindowInsets().getDisplayCutout(),
+ insetsProvider);
+ }
+
+ /** Sets the {@link DisplayCutout}, updating the view to render around the cutout. */
+ public boolean setDisplayCutout(
+ @Nullable DisplayCutout displayCutout,
+ StatusBarContentInsetsProvider insetsProvider) {
+ mDisplayCutout = displayCutout;
updateKeyguardStatusBarHeight();
updatePadding(insetsProvider);
if (mDisplayCutout == null || insetsProvider.currentRotationHasCornerCutout()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
index 45d86c0..f219b9d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
@@ -30,9 +30,11 @@
import android.os.UserManager;
import android.provider.Settings;
import android.util.MathUtils;
+import android.view.DisplayCutout;
import android.view.View;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.core.animation.Animator;
import androidx.core.animation.AnimatorListenerAdapter;
@@ -585,6 +587,17 @@
}
/**
+ * Passes the given {@link DisplayCutout} to the view.
+ *
+ * <p>This isn't needed when the view is part of a real view hierarchy. Only call this when the
+ * view is added to a Compose hierarchy where it doesn't actually receive any callback to its
+ * {@code OnApplyWindowInsetsListener}s.
+ */
+ public void setDisplayCutout(@Nullable DisplayCutout displayCutout) {
+ mView.setDisplayCutout(displayCutout, mInsetsProvider);
+ }
+
+ /**
* @return the alpha to be used to fade out the contents on Keyguard (status bar, bottom area)
* during swiping up.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImpl.kt
index 6b68511..bcc7db1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImpl.kt
@@ -417,10 +417,10 @@
) {
// Reuse the biometric wake-and-unlock transition if we dismiss keyguard from a
// pulse.
- // TODO: Factor this transition out of BiometricUnlockController.
+ // TODO (b/338578036): Factor this transition out of BiometricUnlockController.
biometricUnlockControllerLazy
.get()
- .startWakeAndUnlock(BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING)
+ .startWakeAndUnlock(BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING, null)
}
if (keyguardStateController.isShowing) {
statusBarKeyguardViewManagerLazy
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 0a88d63..74182fc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -1644,6 +1644,10 @@
mScreenOn = false;
}
+ public boolean isScreenOn() {
+ return mScreenOn;
+ }
+
public void setExpansionAffectsAlpha(boolean expansionAffectsAlpha) {
mExpansionAffectsAlpha = expansionAffectsAlpha;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.kt
index bef0b28..08a890d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.kt
@@ -169,16 +169,19 @@
* StatusBarIconController will register all available bindable icons on init (see
* [BindableIconsRepository]), and will ignore any call to setIcon for these.
*
- * [initializer] a view creator that can bind the relevant view models to the created view.
+ * @property initializer a view creator that can bind the relevant view models to the created
+ * view.
+ * @property slot the name of the slot that this holder is used for.
*/
- class BindableIconHolder(val initializer: ModernStatusBarViewCreator) : StatusBarIconHolder() {
+ class BindableIconHolder(val initializer: ModernStatusBarViewCreator, val slot: String) :
+ StatusBarIconHolder() {
override var type: Int = TYPE_BINDABLE
/** This is unused, as bindable icons use their own view binders to control visibility */
override var isVisible: Boolean = true
override fun toString(): String {
- return ("StatusBarIconHolder(type=BINDABLE)")
+ return ("StatusBarIconHolder(type=BINDABLE, slot=$slot)")
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 7301b87..f0dab3b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -744,6 +744,7 @@
public void showBouncer(boolean scrimmed) {
if (DeviceEntryUdfpsRefactor.isEnabled()) {
if (mAlternateBouncerInteractor.canShowAlternateBouncerForFingerprint()) {
+ Log.d(TAG, "showBouncer:alternateBouncer.forceShow()");
mAlternateBouncerInteractor.forceShow();
updateAlternateBouncerShowing(mAlternateBouncerInteractor.isVisibleState());
} else {
@@ -869,6 +870,7 @@
}
if (DeviceEntryUdfpsRefactor.isEnabled()) {
+ Log.d(TAG, "dismissWithAction:alternateBouncer.forceShow()");
mAlternateBouncerInteractor.forceShow();
updateAlternateBouncerShowing(mAlternateBouncerInteractor.isVisibleState());
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/IconManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/IconManager.java
index 0ed9420..5ad7376 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/IconManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/IconManager.java
@@ -37,6 +37,7 @@
import com.android.systemui.statusbar.connectivity.ui.MobileContextProvider;
import com.android.systemui.statusbar.phone.DemoStatusIcons;
import com.android.systemui.statusbar.phone.StatusBarIconHolder;
+import com.android.systemui.statusbar.phone.StatusBarIconHolder.BindableIconHolder;
import com.android.systemui.statusbar.phone.StatusBarLocation;
import com.android.systemui.statusbar.pipeline.mobile.ui.MobileUiAdapter;
import com.android.systemui.statusbar.pipeline.mobile.ui.binder.MobileIconsBinder;
@@ -49,7 +50,9 @@
import com.android.systemui.util.Assert;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
/**
* Turns info from StatusBarIconController into ImageViews in a ViewGroup.
@@ -60,6 +63,11 @@
private final LocationBasedWifiViewModel mWifiViewModel;
private final MobileIconsViewModel mMobileIconsViewModel;
+ /**
+ * Stores the list of bindable icons that have been added, keyed on slot name. This ensures
+ * we don't accidentally add the same bindable icon twice.
+ */
+ private final Map<String, BindableIconHolder> mBindableIcons = new HashMap<>();
protected final Context mContext;
protected int mIconSize;
// Whether or not these icons show up in dumpsys
@@ -142,7 +150,7 @@
case TYPE_MOBILE_NEW -> addNewMobileIcon(index, slot, holder.getTag());
case TYPE_BINDABLE ->
// Safe cast, since only BindableIconHolders can set this tag on themselves
- addBindableIcon((StatusBarIconHolder.BindableIconHolder) holder, index);
+ addBindableIcon((BindableIconHolder) holder, index);
default -> null;
};
}
@@ -162,10 +170,14 @@
* icon view, we can simply create the icon when requested and allow the
* ViewBinder to control its visual state.
*/
- protected StatusIconDisplayable addBindableIcon(StatusBarIconHolder.BindableIconHolder holder,
+ protected StatusIconDisplayable addBindableIcon(BindableIconHolder holder,
int index) {
+ mBindableIcons.put(holder.getSlot(), holder);
ModernStatusBarView view = holder.getInitializer().createAndBind(mContext);
mGroup.addView(view, index, onCreateLayoutParams());
+ if (mIsInDemoMode) {
+ mDemoStatusIcons.addBindableIcon(holder);
+ }
return view;
}
@@ -278,6 +290,9 @@
if (mDemoStatusIcons == null) {
mDemoStatusIcons = createDemoStatusIcons();
mDemoStatusIcons.addModernWifiView(mWifiViewModel);
+ for (BindableIconHolder holder : mBindableIcons.values()) {
+ mDemoStatusIcons.addBindableIcon(holder);
+ }
}
mDemoStatusIcons.onDemoModeStarted();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/StatusBarIconControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/StatusBarIconControllerImpl.java
index 92d90af..fabf858d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/StatusBarIconControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/StatusBarIconControllerImpl.java
@@ -213,7 +213,8 @@
StatusBarIconHolder existingHolder = mStatusBarIconList.getIconHolder(icon.getSlot(), 0);
// Expected to be null
if (existingHolder == null) {
- BindableIconHolder bindableIcon = new BindableIconHolder(icon.getInitializer());
+ BindableIconHolder bindableIcon =
+ new BindableIconHolder(icon.getInitializer(), icon.getSlot());
setIcon(icon.getSlot(), bindableIcon);
} else {
Log.e(TAG, "addBindableIcon called, but icon has already been added. Ignoring");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt
index b80ff38..226a84a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt
@@ -41,6 +41,8 @@
import com.android.systemui.statusbar.pipeline.mobile.util.SubscriptionManagerProxy
import com.android.systemui.statusbar.pipeline.mobile.util.SubscriptionManagerProxyImpl
import com.android.systemui.statusbar.pipeline.satellite.data.DeviceBasedSatelliteRepository
+import com.android.systemui.statusbar.pipeline.satellite.data.DeviceBasedSatelliteRepositorySwitcher
+import com.android.systemui.statusbar.pipeline.satellite.data.RealDeviceBasedSatelliteRepository
import com.android.systemui.statusbar.pipeline.satellite.data.prod.DeviceBasedSatelliteRepositoryImpl
import com.android.systemui.statusbar.pipeline.satellite.ui.viewmodel.DeviceBasedSatelliteViewModel
import com.android.systemui.statusbar.pipeline.satellite.ui.viewmodel.DeviceBasedSatelliteViewModelImpl
@@ -83,8 +85,13 @@
abstract fun connectivityRepository(impl: ConnectivityRepositoryImpl): ConnectivityRepository
@Binds
- abstract fun deviceBasedSatelliteRepository(
+ abstract fun realDeviceBasedSatelliteRepository(
impl: DeviceBasedSatelliteRepositoryImpl
+ ): RealDeviceBasedSatelliteRepository
+
+ @Binds
+ abstract fun deviceBasedSatelliteRepository(
+ impl: DeviceBasedSatelliteRepositorySwitcher
): DeviceBasedSatelliteRepository
@Binds
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/DeviceBasedSatelliteRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/DeviceBasedSatelliteRepository.kt
index ad8b810..d38e834 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/DeviceBasedSatelliteRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/DeviceBasedSatelliteRepository.kt
@@ -17,7 +17,7 @@
package com.android.systemui.statusbar.pipeline.satellite.data
import com.android.systemui.statusbar.pipeline.satellite.shared.model.SatelliteConnectionState
-import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.StateFlow
/**
* Device-based satellite refers to the capability of a device to connect directly to a satellite
@@ -26,12 +26,22 @@
*/
interface DeviceBasedSatelliteRepository {
/** See [SatelliteConnectionState] for available states */
- val connectionState: Flow<SatelliteConnectionState>
+ val connectionState: StateFlow<SatelliteConnectionState>
/** 0-4 level (similar to wifi and mobile) */
// @IntRange(from = 0, to = 4)
- val signalStrength: Flow<Int>
+ val signalStrength: StateFlow<Int>
/** Clients must observe this property, as device-based satellite is location-dependent */
- val isSatelliteAllowedForCurrentLocation: Flow<Boolean>
+ val isSatelliteAllowedForCurrentLocation: StateFlow<Boolean>
}
+
+/**
+ * A no-op interface used for Dagger bindings.
+ *
+ * [DeviceBasedSatelliteRepositorySwitcher] needs to inject both the real repository and the demo
+ * mode repository, both of which implement the [DeviceBasedSatelliteRepository] interface. To help
+ * distinguish the two for the switcher, [DeviceBasedSatelliteRepositoryImpl] will implement this
+ * [RealDeviceBasedSatelliteRepository] interface.
+ */
+interface RealDeviceBasedSatelliteRepository : DeviceBasedSatelliteRepository
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/DeviceBasedSatelliteRepositorySwitcher.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/DeviceBasedSatelliteRepositorySwitcher.kt
new file mode 100644
index 0000000..6b1bc65
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/DeviceBasedSatelliteRepositorySwitcher.kt
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.satellite.data
+
+import android.os.Bundle
+import androidx.annotation.VisibleForTesting
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.demomode.DemoMode
+import com.android.systemui.demomode.DemoModeController
+import com.android.systemui.statusbar.pipeline.satellite.data.demo.DemoDeviceBasedSatelliteRepository
+import com.android.systemui.statusbar.pipeline.satellite.shared.model.SatelliteConnectionState
+import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.mapLatest
+import kotlinx.coroutines.flow.stateIn
+
+/**
+ * A provider for the [DeviceBasedSatelliteRepository] interface that can choose between the Demo
+ * and Prod concrete implementations at runtime. It works by defining a base flow, [activeRepo],
+ * which switches based on the latest information from [DemoModeController], and switches every flow
+ * in the interface to point to the currently-active provider. This allows us to put the demo mode
+ * interface in its own repository, completely separate from the real version, while still using all
+ * of the prod implementations for the rest of the pipeline (interactors and onward). Looks
+ * something like this:
+ * ```
+ * RealRepository
+ * │
+ * ├──►RepositorySwitcher──►RealInteractor──►RealViewModel
+ * │
+ * DemoRepository
+ * ```
+ */
+@OptIn(ExperimentalCoroutinesApi::class)
+@SysUISingleton
+class DeviceBasedSatelliteRepositorySwitcher
+@Inject
+constructor(
+ private val realImpl: RealDeviceBasedSatelliteRepository,
+ private val demoImpl: DemoDeviceBasedSatelliteRepository,
+ private val demoModeController: DemoModeController,
+ @Application scope: CoroutineScope,
+) : DeviceBasedSatelliteRepository {
+ private val isDemoMode =
+ conflatedCallbackFlow {
+ val callback =
+ object : DemoMode {
+ override fun dispatchDemoCommand(command: String?, args: Bundle?) {
+ // Don't care
+ }
+
+ override fun onDemoModeStarted() {
+ demoImpl.startProcessingCommands()
+ trySend(true)
+ }
+
+ override fun onDemoModeFinished() {
+ demoImpl.stopProcessingCommands()
+ trySend(false)
+ }
+ }
+
+ demoModeController.addCallback(callback)
+ awaitClose { demoModeController.removeCallback(callback) }
+ }
+ .stateIn(scope, SharingStarted.WhileSubscribed(), demoModeController.isInDemoMode)
+
+ @VisibleForTesting
+ val activeRepo: StateFlow<DeviceBasedSatelliteRepository> =
+ isDemoMode
+ .mapLatest { isDemoMode ->
+ if (isDemoMode) {
+ demoImpl
+ } else {
+ realImpl
+ }
+ }
+ .stateIn(scope, SharingStarted.WhileSubscribed(), realImpl)
+
+ override val connectionState: StateFlow<SatelliteConnectionState> =
+ activeRepo
+ .flatMapLatest { it.connectionState }
+ .stateIn(scope, SharingStarted.WhileSubscribed(), realImpl.connectionState.value)
+
+ override val signalStrength: StateFlow<Int> =
+ activeRepo
+ .flatMapLatest { it.signalStrength }
+ .stateIn(scope, SharingStarted.WhileSubscribed(), realImpl.signalStrength.value)
+
+ override val isSatelliteAllowedForCurrentLocation: StateFlow<Boolean> =
+ activeRepo
+ .flatMapLatest { it.isSatelliteAllowedForCurrentLocation }
+ .stateIn(
+ scope,
+ SharingStarted.WhileSubscribed(),
+ realImpl.isSatelliteAllowedForCurrentLocation.value
+ )
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/demo/DemoDeviceBasedSatelliteDataSource.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/demo/DemoDeviceBasedSatelliteDataSource.kt
new file mode 100644
index 0000000..7ecc29b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/demo/DemoDeviceBasedSatelliteDataSource.kt
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.satellite.data.demo
+
+import android.os.Bundle
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.demomode.DemoMode
+import com.android.systemui.demomode.DemoModeController
+import com.android.systemui.statusbar.pipeline.satellite.shared.model.SatelliteConnectionState
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.filterNotNull
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.stateIn
+
+/**
+ * Reads the incoming demo commands and emits the satellite-related commands to [satelliteEvents]
+ * for the demo repository to consume.
+ */
+@SysUISingleton
+class DemoDeviceBasedSatelliteDataSource
+@Inject
+constructor(
+ demoModeController: DemoModeController,
+ @Application scope: CoroutineScope,
+) {
+ private val demoCommandStream = demoModeController.demoFlowForCommand(DemoMode.COMMAND_NETWORK)
+ private val _satelliteCommands =
+ demoCommandStream.map { args -> args.toSatelliteEvent() }.filterNotNull()
+
+ /** A flow that emits the demo commands that are satellite-related. */
+ val satelliteEvents =
+ _satelliteCommands.stateIn(scope, SharingStarted.WhileSubscribed(), DEFAULT_VALUE)
+
+ private fun Bundle.toSatelliteEvent(): DemoSatelliteEvent? {
+ val satellite = getString("satellite") ?: return null
+ if (satellite != "show") {
+ return null
+ }
+
+ return DemoSatelliteEvent(
+ connectionState = getString("connection").toConnectionState(),
+ signalStrength = getString("level")?.toInt() ?: 0,
+ )
+ }
+
+ data class DemoSatelliteEvent(
+ val connectionState: SatelliteConnectionState,
+ val signalStrength: Int,
+ )
+
+ private fun String?.toConnectionState(): SatelliteConnectionState {
+ if (this == null) {
+ return SatelliteConnectionState.Unknown
+ }
+ return try {
+ // Lets people use "connected" on the command line and have it be correctly converted
+ // to [SatelliteConnectionState.Connected] with a capital C.
+ SatelliteConnectionState.valueOf(this.replaceFirstChar { it.uppercase() })
+ } catch (e: IllegalArgumentException) {
+ SatelliteConnectionState.Unknown
+ }
+ }
+
+ private companion object {
+ val DEFAULT_VALUE = DemoSatelliteEvent(SatelliteConnectionState.Unknown, signalStrength = 0)
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/demo/DemoDeviceBasedSatelliteRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/demo/DemoDeviceBasedSatelliteRepository.kt
new file mode 100644
index 0000000..56034f0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/demo/DemoDeviceBasedSatelliteRepository.kt
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.satellite.data.demo
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.statusbar.pipeline.satellite.data.DeviceBasedSatelliteRepository
+import com.android.systemui.statusbar.pipeline.satellite.shared.model.SatelliteConnectionState
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.launch
+
+/** A satellite repository that represents the latest satellite values sent via demo mode. */
+@SysUISingleton
+class DemoDeviceBasedSatelliteRepository
+@Inject
+constructor(
+ private val dataSource: DemoDeviceBasedSatelliteDataSource,
+ @Application private val scope: CoroutineScope,
+) : DeviceBasedSatelliteRepository {
+ private var demoCommandJob: Job? = null
+
+ override val connectionState = MutableStateFlow(SatelliteConnectionState.Unknown)
+ override val signalStrength = MutableStateFlow(0)
+ override val isSatelliteAllowedForCurrentLocation = MutableStateFlow(true)
+
+ fun startProcessingCommands() {
+ demoCommandJob =
+ scope.launch { dataSource.satelliteEvents.collect { event -> processEvent(event) } }
+ }
+
+ fun stopProcessingCommands() {
+ demoCommandJob?.cancel()
+ }
+
+ private fun processEvent(event: DemoDeviceBasedSatelliteDataSource.DemoSatelliteEvent) {
+ connectionState.value = event.connectionState
+ signalStrength.value = event.signalStrength
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImpl.kt
index 3e3ea85..a7c4187 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImpl.kt
@@ -31,7 +31,7 @@
import com.android.systemui.log.core.MessageInitializer
import com.android.systemui.log.core.MessagePrinter
import com.android.systemui.statusbar.pipeline.dagger.OemSatelliteInputLog
-import com.android.systemui.statusbar.pipeline.satellite.data.DeviceBasedSatelliteRepository
+import com.android.systemui.statusbar.pipeline.satellite.data.RealDeviceBasedSatelliteRepository
import com.android.systemui.statusbar.pipeline.satellite.data.prod.SatelliteSupport.Companion.whenSupported
import com.android.systemui.statusbar.pipeline.satellite.data.prod.SatelliteSupport.NotSupported
import com.android.systemui.statusbar.pipeline.satellite.data.prod.SatelliteSupport.Supported
@@ -50,12 +50,14 @@
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withContext
@@ -134,7 +136,7 @@
@Application private val scope: CoroutineScope,
@OemSatelliteInputLog private val logBuffer: LogBuffer,
private val systemClock: SystemClock,
-) : DeviceBasedSatelliteRepository {
+) : RealDeviceBasedSatelliteRepository {
private val satelliteManager: SatelliteManager?
@@ -200,10 +202,12 @@
}
override val connectionState =
- satelliteSupport.whenSupported(
- supported = ::connectionStateFlow,
- orElse = flowOf(SatelliteConnectionState.Off)
- )
+ satelliteSupport
+ .whenSupported(
+ supported = ::connectionStateFlow,
+ orElse = flowOf(SatelliteConnectionState.Off)
+ )
+ .stateIn(scope, SharingStarted.Eagerly, SatelliteConnectionState.Off)
// By using the SupportedSatelliteManager here, we expect registration never to fail
private fun connectionStateFlow(sm: SupportedSatelliteManager): Flow<SatelliteConnectionState> =
@@ -227,7 +231,9 @@
.flowOn(bgDispatcher)
override val signalStrength =
- satelliteSupport.whenSupported(supported = ::signalStrengthFlow, orElse = flowOf(0))
+ satelliteSupport
+ .whenSupported(supported = ::signalStrengthFlow, orElse = flowOf(0))
+ .stateIn(scope, SharingStarted.Eagerly, 0)
// By using the SupportedSatelliteManager here, we expect registration never to fail
private fun signalStrengthFlow(sm: SupportedSatelliteManager) =
@@ -312,8 +318,8 @@
}
companion object {
- // TTL for satellite polling is one hour
- const val POLLING_INTERVAL_MS: Long = 1000 * 60 * 60
+ // TTL for satellite polling is twenty minutes
+ const val POLLING_INTERVAL_MS: Long = 1000 * 60 * 20
// Let the system boot up and stabilize before we check for system support
const val MIN_UPTIME: Long = 1000 * 60
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractor.kt
index 054116d..51c053e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractor.kt
@@ -84,14 +84,15 @@
if (Flags.oemEnabledSatelliteFlag()) {
iconsInteractor.icons.aggregateOver(
selector = { intr ->
- combine(intr.isInService, intr.isEmergencyOnly) {
+ combine(intr.isInService, intr.isEmergencyOnly, intr.isNonTerrestrial) {
isInService,
- isEmergencyOnly ->
- !isInService && !isEmergencyOnly
+ isEmergencyOnly,
+ isNtn ->
+ !isInService && !(isEmergencyOnly || isNtn)
}
}
- ) { isOosAndIsNotEmergencyOnly ->
- isOosAndIsNotEmergencyOnly.all { it }
+ ) { isOosAndNotEmergencyOnlyOrSatellite ->
+ isOosAndNotEmergencyOnlyOrSatellite.all { it }
}
} else {
flowOf(false)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
index 37eda64..9273103 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
@@ -17,11 +17,11 @@
package com.android.systemui.statusbar.policy;
import android.annotation.Nullable;
-import android.view.View;
import androidx.annotation.NonNull;
import com.android.systemui.Dumpable;
+import com.android.systemui.animation.Expandable;
import com.android.systemui.demomode.DemoMode;
import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
@@ -51,23 +51,23 @@
*
* Can pass the view that triggered the request.
*/
- void setPowerSaveMode(boolean powerSave, @Nullable View view);
+ void setPowerSaveMode(boolean powerSave, @Nullable Expandable expandable);
/**
* Gets a reference to the last view used when called {@link #setPowerSaveMode}.
*/
@Nullable
- default WeakReference<View> getLastPowerSaverStartView() {
+ default WeakReference<Expandable> getLastPowerSaverStartExpandable() {
return null;
}
/**
* Clears the last view used when called {@link #setPowerSaveMode}.
*
- * Immediately after calling this, a call to {@link #getLastPowerSaverStartView()} should return
- * {@code null}.
+ * Immediately after calling this, a call to {@link #getLastPowerSaverStartExpandable()} should
+ * return {@code null}.
*/
- default void clearLastPowerSaverStartView() {}
+ default void clearLastPowerSaverStartExpandable() {}
/**
* Returns {@code true} if the device is currently plugged in.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
index dab27bb..6012ecd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
@@ -37,7 +37,6 @@
import android.os.PowerManager;
import android.os.PowerSaveState;
import android.util.IndentingPrintWriter;
-import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -48,6 +47,7 @@
import com.android.settingslib.fuelgauge.Estimate;
import com.android.settingslib.utils.PowerUtil;
import com.android.systemui.Dumpable;
+import com.android.systemui.animation.Expandable;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
@@ -110,9 +110,10 @@
private boolean mFetchingEstimate = false;
// Use AtomicReference because we may request it from a different thread
- // Use WeakReference because we are keeping a reference to a View that's not as long lived
- // as this controller.
- private AtomicReference<WeakReference<View>> mPowerSaverStartView = new AtomicReference<>();
+ // Use WeakReference because we are keeping a reference to an Expandable that's not as long
+ // lived as this controller.
+ private AtomicReference<WeakReference<Expandable>> mPowerSaverStartExpandable =
+ new AtomicReference<>();
@VisibleForTesting
public BatteryControllerImpl(
@@ -196,20 +197,20 @@
}
@Override
- public void setPowerSaveMode(boolean powerSave, View view) {
- if (powerSave) mPowerSaverStartView.set(new WeakReference<>(view));
+ public void setPowerSaveMode(boolean powerSave, Expandable expandable) {
+ if (powerSave) mPowerSaverStartExpandable.set(new WeakReference<>(expandable));
BatterySaverUtils.setPowerSaveMode(mContext, powerSave, /*needFirstTimeWarning*/ true,
SAVER_ENABLED_QS);
}
@Override
- public WeakReference<View> getLastPowerSaverStartView() {
- return mPowerSaverStartView.get();
+ public WeakReference<Expandable> getLastPowerSaverStartExpandable() {
+ return mPowerSaverStartExpandable.get();
}
@Override
- public void clearLastPowerSaverStartView() {
- mPowerSaverStartView.set(null);
+ public void clearLastPowerSaverStartExpandable() {
+ mPowerSaverStartExpandable.set(null);
}
@Override
@@ -543,4 +544,4 @@
public boolean isChargingSourceDock() {
return mPluggedChargingSource == BatteryManager.BATTERY_PLUGGED_DOCK;
}
-}
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt b/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt
index 37be1c6..a817b31 100644
--- a/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt
@@ -18,6 +18,7 @@
package com.android.systemui.user.data.repository
import android.annotation.SuppressLint
+import android.annotation.UserIdInt
import android.content.Context
import android.content.pm.UserInfo
import android.os.UserHandle
@@ -107,6 +108,22 @@
fun isSimpleUserSwitcher(): Boolean
fun isUserSwitcherEnabled(): Boolean
+
+ /**
+ * Returns the user ID of the "main user" of the device. This user may have access to certain
+ * features which are limited to at most one user. There will never be more than one main user
+ * on a device.
+ *
+ * <p>Currently, on most form factors the first human user on the device will be the main user;
+ * in the future, the concept may be transferable, so a different user (or even no user at all)
+ * may be designated the main user instead. On other form factors there might not be a main
+ * user.
+ *
+ * <p> When the device doesn't have a main user, this will return {@code null}.
+ *
+ * @see [UserManager.getMainUser]
+ */
+ @UserIdInt suspend fun getMainUserId(): Int?
}
@SysUISingleton
@@ -239,6 +256,10 @@
return _userSwitcherSettings.value.isUserSwitcherEnabled
}
+ override suspend fun getMainUserId(): Int? {
+ return withContext(backgroundDispatcher) { manager.mainUser?.identifier }
+ }
+
private suspend fun getSettings(): UserSwitcherSettingsModel {
return withContext(backgroundDispatcher) {
val isSimpleUserSwitcher =
diff --git a/packages/SystemUI/src/com/android/systemui/user/domain/interactor/SelectedUserInteractor.kt b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/SelectedUserInteractor.kt
index 38b381a..59c819d 100644
--- a/packages/SystemUI/src/com/android/systemui/user/domain/interactor/SelectedUserInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/SelectedUserInteractor.kt
@@ -2,6 +2,7 @@
import android.annotation.UserIdInt
import android.content.pm.UserInfo
+import android.os.UserManager
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.Flags.refactorGetCurrentUser
import com.android.systemui.dagger.SysUISingleton
@@ -38,4 +39,23 @@
KeyguardUpdateMonitor.getCurrentUser()
}
}
+
+ /**
+ * Returns the user ID of the "main user" of the device. This user may have access to certain
+ * features which are limited to at most one user. There will never be more than one main user
+ * on a device.
+ *
+ * <p>Currently, on most form factors the first human user on the device will be the main user;
+ * in the future, the concept may be transferable, so a different user (or even no user at all)
+ * may be designated the main user instead. On other form factors there might not be a main
+ * user.
+ *
+ * <p> When the device doesn't have a main user, this will return {@code null}.
+ *
+ * @see [UserManager.getMainUser]
+ */
+ @UserIdInt
+ fun getMainUserId(): Int? {
+ return repository.mainUserId
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/util/kotlin/BooleanFlowOperators.kt b/packages/SystemUI/src/com/android/systemui/util/kotlin/BooleanFlowOperators.kt
index b300885..a2759c6 100644
--- a/packages/SystemUI/src/com/android/systemui/util/kotlin/BooleanFlowOperators.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/kotlin/BooleanFlowOperators.kt
@@ -28,11 +28,23 @@
*
* Usage:
* ```
- * val result = and(flow1, flow2)
+ * val result = allOf(flow1, flow2)
* ```
*/
- fun and(vararg flows: Flow<Boolean>): Flow<Boolean> =
- combine(flows.asIterable()) { values -> values.all { it } }.distinctUntilChanged()
+ fun allOf(vararg flows: Flow<Boolean>): Flow<Boolean> = flows.asIterable().all()
+
+ /**
+ * Logical AND operator for boolean flows. Will collect all flows and [combine] them to
+ * determine the result.
+ */
+ fun Array<Flow<Boolean>>.all(): Flow<Boolean> = allOf(*this)
+
+ /**
+ * Logical AND operator for boolean flows. Will collect all flows and [combine] them to
+ * determine the result.
+ */
+ fun Iterable<Flow<Boolean>>.all(): Flow<Boolean> =
+ combine(this) { values -> values.all { it } }.distinctUntilChanged()
/**
* Logical NOT operator for a boolean flow.
@@ -48,6 +60,36 @@
* Logical OR operator for a boolean flow. Will collect all flows and [combine] them to
* determine the result.
*/
- fun or(vararg flows: Flow<Boolean>): Flow<Boolean> =
- combine(flows.asIterable()) { values -> values.any { it } }.distinctUntilChanged()
+ fun anyOf(vararg flows: Flow<Boolean>): Flow<Boolean> = flows.asIterable().any()
+
+ /**
+ * Logical OR operator for a boolean flow. Will collect all flows and [combine] them to
+ * determine the result.
+ */
+ fun Array<Flow<Boolean>>.any(): Flow<Boolean> = anyOf(*this)
+
+ /**
+ * Logical OR operator for a boolean flow. Will collect all flows and [combine] them to
+ * determine the result.
+ */
+ fun Iterable<Flow<Boolean>>.any(): Flow<Boolean> =
+ combine(this) { values -> values.any { it } }.distinctUntilChanged()
+
+ /**
+ * Returns a Flow that produces `true` when all input flows are producing `false`, otherwise
+ * produces `false`.
+ */
+ fun noneOf(vararg flows: Flow<Boolean>): Flow<Boolean> = not(anyOf(*flows))
+
+ /**
+ * Returns a Flow that produces `true` when all input flows are producing `false`, otherwise
+ * produces `false`.
+ */
+ fun Array<Flow<Boolean>>.none(): Flow<Boolean> = noneOf(*this)
+
+ /**
+ * Returns a Flow that produces `true` when all input flows are producing `false`, otherwise
+ * produces `false`.
+ */
+ fun Iterable<Flow<Boolean>>.none(): Flow<Boolean> = not(any())
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractor.kt
index ed44699..3eec3d9 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractor.kt
@@ -68,13 +68,9 @@
communicationDevice?.toAudioOutputDevice()
}
} else {
- mediaOutputInteractor.defaultActiveMediaSession
- .flatMapLatest {
- localMediaRepositoryFactory
- .create(it?.packageName)
- .currentConnectedDevice
- }
- .map { mediaDevice -> mediaDevice?.toAudioOutputDevice() }
+ mediaOutputInteractor.currentConnectedDevice.map { mediaDevice ->
+ mediaDevice?.toAudioOutputDevice()
+ }
}
}
.map { it ?: AudioOutputDevice.Unknown }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/data/repository/AncSliceRepository.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/data/repository/AncSliceRepository.kt
index 8ce3b1f..3117abc 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/data/repository/AncSliceRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/data/repository/AncSliceRepository.kt
@@ -23,6 +23,7 @@
import com.android.settingslib.bluetooth.BluetoothUtils
import com.android.settingslib.media.BluetoothMediaDevice
import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.slice.sliceForUri
import com.android.systemui.volume.panel.component.mediaoutput.data.repository.LocalMediaRepositoryFactory
import dagger.assisted.Assisted
@@ -57,6 +58,7 @@
constructor(
mediaRepositoryFactory: LocalMediaRepositoryFactory,
@Background private val backgroundCoroutineContext: CoroutineContext,
+ @Main private val mainCoroutineContext: CoroutineContext,
@Assisted private val sliceViewManager: SliceViewManager,
) : AncSliceRepository {
@@ -73,7 +75,7 @@
.distinctUntilChanged()
.flatMapLatest { sliceUri ->
sliceUri ?: return@flatMapLatest flowOf(null)
- sliceViewManager.sliceForUri(sliceUri)
+ sliceViewManager.sliceForUri(sliceUri).flowOn(mainCoroutineContext)
}
.flowOn(backgroundCoroutineContext)
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/ui/viewmodel/AncViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/ui/viewmodel/AncViewModel.kt
index bee79bb..c980eb4 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/ui/viewmodel/AncViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/ui/viewmodel/AncViewModel.kt
@@ -16,7 +16,9 @@
package com.android.systemui.volume.panel.component.anc.ui.viewmodel
+import android.content.Intent
import androidx.slice.Slice
+import androidx.slice.SliceItem
import com.android.systemui.volume.panel.component.anc.domain.AncAvailabilityCriteria
import com.android.systemui.volume.panel.component.anc.domain.interactor.AncSliceInteractor
import com.android.systemui.volume.panel.component.anc.domain.model.AncSlices
@@ -59,6 +61,31 @@
.map { it.buttonSlice }
.stateIn(coroutineScope, SharingStarted.Eagerly, null)
+ fun isClickable(slice: Slice?): Boolean {
+ slice ?: return false
+ val slices = ArrayDeque<SliceItem>()
+ slices.addAll(slice.items)
+ while (slices.isNotEmpty()) {
+ val item: SliceItem = slices.removeFirst()
+ when (item.format) {
+ android.app.slice.SliceItem.FORMAT_ACTION -> {
+ val itemActionIntent: Intent? = item.action?.intent
+ if (itemActionIntent?.hasExtra(EXTRA_ANC_ENABLED) == true) {
+ return itemActionIntent.getBooleanExtra(EXTRA_ANC_ENABLED, true)
+ }
+ }
+ android.app.slice.SliceItem.FORMAT_SLICE -> {
+ item.slice?.items?.let(slices::addAll)
+ }
+ }
+ }
+ return true
+ }
+
+ private companion object {
+ const val EXTRA_ANC_ENABLED = "EXTRA_ANC_ENABLED"
+ }
+
/** Call this to update [popupSlice] width in a reaction to container size change. */
fun onPopupSliceWidthChanged(width: Int) {
interactor.onPopupSliceWidthChanged(width)
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/MediaOutputAvailabilityCriteria.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/MediaOutputAvailabilityCriteria.kt
deleted file mode 100644
index bac7d15..0000000
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/MediaOutputAvailabilityCriteria.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.volume.panel.component.mediaoutput.domain
-
-import com.android.settingslib.volume.domain.interactor.AudioModeInteractor
-import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope
-import com.android.systemui.volume.panel.domain.ComponentAvailabilityCriteria
-import javax.inject.Inject
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.map
-
-/** Determines if the Media Output Volume Panel component is available. */
-@VolumePanelScope
-class MediaOutputAvailabilityCriteria
-@Inject
-constructor(
- private val audioModeInteractor: AudioModeInteractor,
-) : ComponentAvailabilityCriteria {
-
- override fun isAvailable(): Flow<Boolean> = audioModeInteractor.isOngoingCall.map { !it }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputActionsInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputActionsInteractor.kt
index 22c0530..199bc3b 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputActionsInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputActionsInteractor.kt
@@ -33,15 +33,15 @@
private val mediaOutputDialogManager: MediaOutputDialogManager,
) {
- fun onBarClick(sessionWithPlaybackState: SessionWithPlaybackState?, expandable: Expandable) {
+ fun onBarClick(sessionWithPlaybackState: SessionWithPlaybackState?, expandable: Expandable?) {
if (sessionWithPlaybackState?.isPlaybackActive == true) {
mediaOutputDialogManager.createAndShowWithController(
sessionWithPlaybackState.session.packageName,
false,
- expandable.dialogController()
+ expandable?.dialogController()
)
} else {
- mediaOutputDialogManager.createAndShowForSystemRouting(expandable.dialogController())
+ mediaOutputDialogManager.createAndShowForSystemRouting(expandable?.dialogController())
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputInteractor.kt
index 83b8029..b00829e 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputInteractor.kt
@@ -19,28 +19,34 @@
import android.content.pm.PackageManager
import android.media.VolumeProvider
import android.media.session.MediaController
+import android.os.Handler
import android.util.Log
import com.android.settingslib.media.MediaDevice
import com.android.settingslib.volume.data.repository.LocalMediaRepository
import com.android.settingslib.volume.data.repository.MediaControllerRepository
+import com.android.settingslib.volume.data.repository.stateChanges
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.volume.panel.component.mediaoutput.data.repository.LocalMediaRepositoryFactory
import com.android.systemui.volume.panel.component.mediaoutput.domain.model.MediaDeviceSessions
import com.android.systemui.volume.panel.component.mediaoutput.shared.model.MediaDeviceSession
import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope
+import com.android.systemui.volume.panel.shared.model.Result
+import com.android.systemui.volume.panel.shared.model.filterData
+import com.android.systemui.volume.panel.shared.model.wrapInResult
import javax.inject.Inject
import kotlin.coroutines.CoroutineContext
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
-import kotlinx.coroutines.flow.shareIn
+import kotlinx.coroutines.flow.merge
+import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.withContext
@@ -55,24 +61,34 @@
@VolumePanelScope private val coroutineScope: CoroutineScope,
@Background private val backgroundCoroutineContext: CoroutineContext,
mediaControllerRepository: MediaControllerRepository,
+ @Background private val backgroundHandler: Handler,
) {
private val activeMediaControllers: Flow<MediaControllers> =
mediaControllerRepository.activeSessions
+ .flatMapLatest { activeSessions ->
+ activeSessions
+ .map { activeSession -> activeSession.stateChanges() }
+ .merge()
+ .map { activeSessions }
+ .onStart { emit(activeSessions) }
+ }
.map { getMediaControllers(it) }
- .shareIn(coroutineScope, SharingStarted.Eagerly, replay = 1)
+ .stateIn(coroutineScope, SharingStarted.Eagerly, MediaControllers(null, null))
/** [MediaDeviceSessions] that contains currently active sessions. */
val activeMediaDeviceSessions: Flow<MediaDeviceSessions> =
- activeMediaControllers.map {
- MediaDeviceSessions(
- local = it.local?.mediaDeviceSession(),
- remote = it.remote?.mediaDeviceSession()
- )
- }
+ activeMediaControllers
+ .map {
+ MediaDeviceSessions(
+ local = it.local?.mediaDeviceSession(),
+ remote = it.remote?.mediaDeviceSession()
+ )
+ }
+ .stateIn(coroutineScope, SharingStarted.Eagerly, MediaDeviceSessions(null, null))
/** Returns the default [MediaDeviceSession] from [activeMediaDeviceSessions] */
- val defaultActiveMediaSession: StateFlow<MediaDeviceSession?> =
+ val defaultActiveMediaSession: StateFlow<Result<MediaDeviceSession?>> =
activeMediaControllers
.map {
when {
@@ -82,15 +98,21 @@
else -> null
}
}
+ .wrapInResult()
.flowOn(backgroundCoroutineContext)
- .stateIn(coroutineScope, SharingStarted.Eagerly, null)
+ .stateIn(coroutineScope, SharingStarted.Eagerly, Result.Loading())
- private val localMediaRepository: SharedFlow<LocalMediaRepository> =
+ private val localMediaRepository: Flow<LocalMediaRepository> =
defaultActiveMediaSession
+ .filterData()
.map { it?.packageName }
.distinctUntilChanged()
.map { localMediaRepositoryFactory.create(it) }
- .shareIn(coroutineScope, SharingStarted.Eagerly, replay = 1)
+ .stateIn(
+ coroutineScope,
+ SharingStarted.Eagerly,
+ localMediaRepositoryFactory.create(null)
+ )
/** Currently connected [MediaDevice]. */
val currentConnectedDevice: Flow<MediaDevice?> =
@@ -129,21 +151,33 @@
}
if (!remoteMediaSessions.contains(controller.packageName)) {
remoteMediaSessions.add(controller.packageName)
- if (remoteController == null) {
- remoteController = controller
- }
+ remoteController = chooseController(remoteController, controller)
}
}
MediaController.PlaybackInfo.PLAYBACK_TYPE_LOCAL -> {
if (controller.packageName in remoteMediaSessions) continue
- if (localController != null) continue
- localController = controller
+ localController = chooseController(localController, controller)
}
}
}
return MediaControllers(local = localController, remote = remoteController)
}
+ private fun chooseController(
+ currentController: MediaController?,
+ newController: MediaController,
+ ): MediaController {
+ if (currentController == null) {
+ return newController
+ }
+ val isNewControllerActive = newController.playbackState?.isActive == true
+ val isCurrentControllerActive = currentController.playbackState?.isActive == true
+ if (isNewControllerActive && !isCurrentControllerActive) {
+ return newController
+ }
+ return currentController
+ }
+
private suspend fun MediaController.mediaDeviceSession(): MediaDeviceSession? {
return MediaDeviceSession(
packageName = packageName,
@@ -155,6 +189,14 @@
)
}
+ private fun MediaController?.stateChanges(): Flow<MediaController?> {
+ if (this == null) {
+ return flowOf(null)
+ }
+
+ return stateChanges(backgroundHandler).map { this }.onStart { emit(this@stateChanges) }
+ }
+
private data class MediaControllers(
val local: MediaController?,
val remote: MediaController?,
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModel.kt
index d60d981..be3a529 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModel.kt
@@ -18,16 +18,21 @@
import android.content.Context
import com.android.internal.logging.UiEventLogger
+import com.android.settingslib.volume.domain.interactor.AudioModeInteractor
import com.android.systemui.animation.Expandable
import com.android.systemui.common.shared.model.Color
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.res.R
+import com.android.systemui.volume.domain.interactor.AudioOutputInteractor
+import com.android.systemui.volume.domain.model.AudioOutputDevice
import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaDeviceSessionInteractor
import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaOutputActionsInteractor
import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaOutputInteractor
import com.android.systemui.volume.panel.component.mediaoutput.shared.model.SessionWithPlaybackState
import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope
import com.android.systemui.volume.panel.shared.model.Result
+import com.android.systemui.volume.panel.shared.model.filterData
+import com.android.systemui.volume.panel.shared.model.wrapInResult
import com.android.systemui.volume.panel.ui.VolumePanelUiEvent
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
@@ -35,6 +40,7 @@
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.mapNotNull
@@ -50,25 +56,25 @@
@VolumePanelScope private val coroutineScope: CoroutineScope,
private val actionsInteractor: MediaOutputActionsInteractor,
private val mediaDeviceSessionInteractor: MediaDeviceSessionInteractor,
+ audioOutputInteractor: AudioOutputInteractor,
+ audioModeInteractor: AudioModeInteractor,
interactor: MediaOutputInteractor,
private val uiEventLogger: UiEventLogger,
) {
private val sessionWithPlaybackState: StateFlow<Result<SessionWithPlaybackState?>> =
interactor.defaultActiveMediaSession
+ .filterData()
.flatMapLatest { session ->
if (session == null) {
- flowOf(Result.Data<SessionWithPlaybackState?>(null))
+ flowOf(null)
} else {
mediaDeviceSessionInteractor.playbackState(session).mapNotNull { playback ->
- playback?.let {
- Result.Data<SessionWithPlaybackState?>(
- SessionWithPlaybackState(session, playback.isActive())
- )
- }
+ playback?.let { SessionWithPlaybackState(session, playback.isActive) }
}
}
}
+ .wrapInResult()
.stateIn(
coroutineScope,
SharingStarted.Eagerly,
@@ -76,23 +82,24 @@
)
val connectedDeviceViewModel: StateFlow<ConnectedDeviceViewModel?> =
- combine(sessionWithPlaybackState, interactor.currentConnectedDevice) {
- mediaDeviceSession,
- currentConnectedDevice ->
- if (mediaDeviceSession !is Result.Data) {
- return@combine null
- }
- ConnectedDeviceViewModel(
- if (mediaDeviceSession.data?.isPlaybackActive == true) {
- context.getString(
- R.string.media_output_label_title,
- mediaDeviceSession.data.session.appLabel
- )
- } else {
- context.getString(R.string.media_output_title_without_playing)
- },
- currentConnectedDevice?.name,
- )
+ combine(
+ sessionWithPlaybackState.filterData(),
+ audioModeInteractor.isOngoingCall,
+ audioOutputInteractor.currentAudioDevice.filter {
+ it !is AudioOutputDevice.Unknown
+ },
+ ) { mediaDeviceSession, isOngoingCall, currentConnectedDevice ->
+ val label =
+ when {
+ isOngoingCall -> context.getString(R.string.media_output_title_ongoing_call)
+ mediaDeviceSession?.isPlaybackActive == true ->
+ context.getString(
+ R.string.media_output_label_title,
+ mediaDeviceSession.session.appLabel
+ )
+ else -> context.getString(R.string.media_output_title_without_playing)
+ }
+ ConnectedDeviceViewModel(label, currentConnectedDevice.name)
}
.stateIn(
coroutineScope,
@@ -101,16 +108,16 @@
)
val deviceIconViewModel: StateFlow<DeviceIconViewModel?> =
- combine(sessionWithPlaybackState, interactor.currentConnectedDevice) {
+ combine(sessionWithPlaybackState.filterData(), audioOutputInteractor.currentAudioDevice) {
mediaDeviceSession,
currentConnectedDevice ->
- if (mediaDeviceSession !is Result.Data) {
- return@combine null
- }
val icon: Icon =
- currentConnectedDevice?.icon?.let { Icon.Loaded(it, null) }
+ currentConnectedDevice
+ .takeIf { currentConnectedDevice !is AudioOutputDevice.Unknown }
+ ?.icon
+ ?.let { Icon.Loaded(it, null) }
?: Icon.Resource(R.drawable.ic_media_home_devices, null)
- if (mediaDeviceSession.data?.isPlaybackActive == true) {
+ if (mediaDeviceSession?.isPlaybackActive == true) {
DeviceIconViewModel.IsPlaying(
icon = icon,
iconColor =
@@ -136,7 +143,7 @@
null,
)
- fun onBarClick(expandable: Expandable) {
+ fun onBarClick(expandable: Expandable?) {
uiEventLogger.log(VolumePanelUiEvent.VOLUME_PANEL_MEDIA_OUTPUT_CLICKED)
val result = sessionWithPlaybackState.value
actionsInteractor.onBarClick((result as? Result.Data)?.data, expandable)
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/interactor/AudioSlidersInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/interactor/AudioSlidersInteractor.kt
index ac8092c..fa40059 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/interactor/AudioSlidersInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/interactor/AudioSlidersInteractor.kt
@@ -25,6 +25,7 @@
import com.android.systemui.volume.panel.component.mediaoutput.shared.model.isTheSameSession
import com.android.systemui.volume.panel.component.volume.domain.model.SliderType
import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope
+import com.android.systemui.volume.panel.shared.model.filterData
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.coroutineScope
@@ -46,7 +47,7 @@
val volumePanelSliders: StateFlow<List<SliderType>> =
combineTransform(
mediaOutputInteractor.activeMediaDeviceSessions,
- mediaOutputInteractor.defaultActiveMediaSession,
+ mediaOutputInteractor.defaultActiveMediaSession.filterData(),
audioRepository.communicationDevice,
) { activeSessions, defaultSession, communicationDevice ->
coroutineScope {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/AudioVolumeComponentViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/AudioVolumeComponentViewModel.kt
index 741f5cf..26d6a9a 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/AudioVolumeComponentViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/AudioVolumeComponentViewModel.kt
@@ -26,6 +26,7 @@
import com.android.systemui.volume.panel.component.volume.slider.ui.viewmodel.CastVolumeSliderViewModel
import com.android.systemui.volume.panel.component.volume.slider.ui.viewmodel.SliderViewModel
import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope
+import com.android.systemui.volume.panel.shared.model.filterData
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -80,9 +81,13 @@
val isExpanded: StateFlow<Boolean> =
merge(
mutableIsExpanded,
- mediaOutputInteractor.defaultActiveMediaSession.flatMapLatest {
- if (it == null) flowOf(true)
- else mediaDeviceSessionInteractor.playbackState(it).map { it?.isActive != true }
+ mediaOutputInteractor.defaultActiveMediaSession.filterData().flatMapLatest { session
+ ->
+ if (session == null) flowOf(true)
+ else
+ mediaDeviceSessionInteractor.playbackState(session).map {
+ it?.isActive != true
+ }
},
)
.stateIn(scope, SharingStarted.Eagerly, false)
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/shared/model/Result.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/shared/model/Result.kt
index 8793538..5daed99 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/shared/model/Result.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/shared/model/Result.kt
@@ -16,6 +16,10 @@
package com.android.systemui.volume.panel.shared.model
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.mapNotNull
+
/** Models a loadable result */
sealed interface Result<T> {
@@ -25,3 +29,9 @@
/** The data is loaded successfully */
data class Data<T>(val data: T) : Result<T>
}
+
+/** Wraps flow into [Result]. */
+fun <T> Flow<T>.wrapInResult(): Flow<Result<T>> = map { Result.Data(it) }
+
+/** Filters only [Result.Data] from the flow. */
+fun <T> Flow<Result<T>>.filterData(): Flow<T> = mapNotNull { it as? Result.Data<T> }.map { it.data }
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
index 263ddc1..b86a7c9 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
@@ -21,6 +21,7 @@
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BUBBLES_MANAGE_MENU_EXPANDED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_DIALOG_SHOWING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_FREEFORM_ACTIVE_IN_DESKTOP_MODE;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_DISABLE_GESTURE_SPLIT_INVOCATION;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_ONE_HANDED_ACTIVE;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
@@ -273,6 +274,13 @@
splitScreen.setSplitscreenFocus(leftOrTop);
}
});
+ splitScreen.registerSplitAnimationListener(new SplitScreen.SplitInvocationListener() {
+ @Override
+ public void onSplitAnimationInvoked(boolean animationRunning) {
+ mSysUiState.setFlag(SYSUI_STATE_DISABLE_GESTURE_SPLIT_INVOCATION, animationRunning)
+ .commitUpdate(mDisplayTracker.getDefaultDisplayId());
+ }
+ }, mSysUiMainExecutor);
}
@VisibleForTesting
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogManagerTest.java
index abc12ed..e9c742d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogManagerTest.java
@@ -24,7 +24,6 @@
import android.bluetooth.BluetoothDevice;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
-import android.view.View;
import androidx.test.filters.SmallTest;
@@ -34,6 +33,7 @@
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.animation.DialogTransitionAnimator;
+import com.android.systemui.animation.Expandable;
import com.android.systemui.statusbar.phone.SystemUIDialog;
import org.junit.Before;
@@ -56,9 +56,10 @@
@Rule
public MockitoRule mockito = MockitoJUnit.rule();
- private final View mView = new View(mContext);
private final List<CachedBluetoothDevice> mCachedDevices = new ArrayList<>();
@Mock
+ private Expandable mExpandable;
+ @Mock
private DialogTransitionAnimator mDialogTransitionAnimator;
@Mock
private HearingDevicesDialogDelegate.Factory mDialogFactory;
@@ -97,7 +98,7 @@
public void showDialog_bluetoothDisable_showPairNewDeviceTrue() {
when(mLocalBluetoothAdapter.isEnabled()).thenReturn(false);
- mManager.showDialog(mView);
+ mManager.showDialog(mExpandable);
verify(mDialogFactory).create(eq(true));
}
@@ -109,7 +110,7 @@
when(mCachedDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
mCachedDevices.add(mCachedDevice);
- mManager.showDialog(mView);
+ mManager.showDialog(mExpandable);
verify(mDialogFactory).create(eq(false));
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/TransitionAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/TransitionAnimatorTest.kt
index fbe1184..e64df90 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/animation/TransitionAnimatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/animation/TransitionAnimatorTest.kt
@@ -28,10 +28,13 @@
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
+import platform.test.motion.MotionTestRule
import platform.test.motion.RecordedMotion
-import platform.test.motion.Sampling.Companion.evenlySampled
+import platform.test.motion.view.AnimationSampling.Companion.evenlySampled
import platform.test.motion.view.DrawableFeatureCaptures
-import platform.test.motion.view.ViewMotionTestRule
+import platform.test.motion.view.ViewRecordingSpec.Companion.captureWithoutScreenshot
+import platform.test.motion.view.ViewToolkit
+import platform.test.motion.view.record
import platform.test.screenshot.DeviceEmulationRule
import platform.test.screenshot.DeviceEmulationSpec
import platform.test.screenshot.DisplaySpec
@@ -64,7 +67,8 @@
@get:Rule(order = 0) val deviceEmulationRule = DeviceEmulationRule(emulationSpec)
@get:Rule(order = 1) val activityRule = ActivityScenarioRule(EmptyTestActivity::class.java)
- @get:Rule(order = 2) val motionRule = ViewMotionTestRule(pathManager, { activityRule.scenario })
+ @get:Rule(order = 2)
+ val motionRule = MotionTestRule(ViewToolkit { activityRule.scenario }, pathManager)
@Test
fun backgroundAnimation_whenLaunching() {
@@ -151,15 +155,14 @@
backgroundLayer: GradientDrawable,
animator: AnimatorSet
): RecordedMotion {
- return motionRule.checkThat(animator).record(
- backgroundLayer,
- evenlySampled(20),
- visualCapture = null
- ) {
- capture(DrawableFeatureCaptures.bounds, "bounds")
- capture(DrawableFeatureCaptures.cornerRadii, "corner_radii")
- capture(DrawableFeatureCaptures.alpha, "alpha")
- }
+ return motionRule.record(
+ animator,
+ backgroundLayer.captureWithoutScreenshot(evenlySampled(20)) {
+ feature(DrawableFeatureCaptures.bounds, "bounds")
+ feature(DrawableFeatureCaptures.cornerRadii, "corner_radii")
+ feature(DrawableFeatureCaptures.alpha, "alpha")
+ }
+ )
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthDialogPanelInteractionDetectorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthDialogPanelInteractionDetectorTest.kt
index 67ca9a4..0231486 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthDialogPanelInteractionDetectorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthDialogPanelInteractionDetectorTest.kt
@@ -16,80 +16,73 @@
package com.android.systemui.biometrics
+import android.platform.test.flag.junit.FlagsParameterization
import androidx.test.filters.SmallTest
-import com.android.systemui.SysUITestComponent
-import com.android.systemui.SysUITestModule
import com.android.systemui.SysuiTestCase
-import com.android.systemui.biometrics.domain.BiometricsDomainLayerModule
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.flags.FakeFeatureFlagsClassicModule
-import com.android.systemui.flags.Flags
-import com.android.systemui.runCurrent
-import com.android.systemui.runTest
-import com.android.systemui.shade.data.repository.FakeShadeRepository
-import com.android.systemui.user.domain.UserDomainLayerModule
-import dagger.BindsInstance
-import dagger.Component
+import com.android.systemui.flags.andSceneContainer
+import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.shade.domain.interactor.shadeInteractor
+import com.android.systemui.shade.shadeTestUtil
+import com.android.systemui.testKosmos
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
+import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.Mockito.verify
-import org.mockito.Mockito.verifyZeroInteractions
import org.mockito.MockitoAnnotations
+import org.mockito.kotlin.verifyZeroInteractions
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4
+import platform.test.runner.parameterized.Parameters
@SmallTest
-class AuthDialogPanelInteractionDetectorTest : SysuiTestCase() {
+@RunWith(ParameterizedAndroidJunit4::class)
+class AuthDialogPanelInteractionDetectorTest(flags: FlagsParameterization?) : SysuiTestCase() {
- @SysUISingleton
- @Component(
- modules =
- [
- SysUITestModule::class,
- UserDomainLayerModule::class,
- BiometricsDomainLayerModule::class,
- ]
- )
- interface TestComponent : SysUITestComponent<AuthDialogPanelInteractionDetector> {
-
- val shadeRepository: FakeShadeRepository
-
- @Component.Factory
- interface Factory {
- fun create(
- @BindsInstance test: SysuiTestCase,
- featureFlags: FakeFeatureFlagsClassicModule,
- ): TestComponent
+ companion object {
+ @JvmStatic
+ @Parameters(name = "{0}")
+ fun getParams(): List<FlagsParameterization> {
+ return FlagsParameterization.allCombinationsOf().andSceneContainer()
}
}
- private val testComponent: TestComponent =
- DaggerAuthDialogPanelInteractionDetectorTest_TestComponent.factory()
- .create(
- test = this,
- featureFlags =
- FakeFeatureFlagsClassicModule { set(Flags.FULL_SCREEN_USER_SWITCHER, true) },
- )
+ init {
+ mSetFlagsRule.setFlagsParameterization(flags!!)
+ }
- private val detector: AuthDialogPanelInteractionDetector = testComponent.underTest
+ private val kosmos = testKosmos()
+ private val testScope = kosmos.testScope
+
+ private val shadeTestUtil by lazy { kosmos.shadeTestUtil }
@Mock private lateinit var action: Runnable
+ lateinit var detector: AuthDialogPanelInteractionDetector
+
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
+ detector =
+ AuthDialogPanelInteractionDetector(
+ kosmos.applicationCoroutineScope,
+ { kosmos.shadeInteractor },
+ )
}
@Test
fun enableDetector_expand_shouldRunAction() =
- testComponent.runTest {
+ testScope.runTest {
// GIVEN shade is closed and detector is enabled
- shadeRepository.setLegacyShadeExpansion(0f)
+ shadeTestUtil.setShadeExpansion(0f)
detector.enable(action)
runCurrent()
// WHEN shade expands
- shadeRepository.setLegacyShadeTracking(true)
- shadeRepository.setLegacyShadeExpansion(.5f)
+ shadeTestUtil.setTracking(true)
+ shadeTestUtil.setShadeExpansion(.5f)
runCurrent()
// THEN action was run
@@ -98,9 +91,9 @@
@Test
fun enableDetector_isUserInteractingTrue_shouldNotPostRunnable() =
- testComponent.runTest {
+ testScope.runTest {
// GIVEN isInteracting starts true
- shadeRepository.setLegacyShadeTracking(true)
+ shadeTestUtil.setTracking(true)
runCurrent()
detector.enable(action)
@@ -110,33 +103,34 @@
@Test
fun enableDetector_shadeExpandImmediate_shouldNotPostRunnable() =
- testComponent.runTest {
+ testScope.runTest {
// GIVEN shade is closed and detector is enabled
- shadeRepository.setLegacyShadeExpansion(0f)
+ shadeTestUtil.setShadeExpansion(0f)
detector.enable(action)
runCurrent()
// WHEN shade expands fully instantly
- shadeRepository.setLegacyShadeExpansion(1f)
+ shadeTestUtil.setShadeExpansion(1f)
runCurrent()
// THEN action not run
verifyZeroInteractions(action)
+ detector.disable()
}
@Test
fun disableDetector_shouldNotPostRunnable() =
- testComponent.runTest {
+ testScope.runTest {
// GIVEN shade is closed and detector is enabled
- shadeRepository.setLegacyShadeExpansion(0f)
+ shadeTestUtil.setShadeExpansion(0f)
detector.enable(action)
runCurrent()
// WHEN detector is disabled and shade opens
detector.disable()
runCurrent()
- shadeRepository.setLegacyShadeTracking(true)
- shadeRepository.setLegacyShadeExpansion(.5f)
+ shadeTestUtil.setTracking(true)
+ shadeTestUtil.setShadeExpansion(.5f)
runCurrent()
// THEN action not run
@@ -145,17 +139,18 @@
@Test
fun enableDetector_beginCollapse_shouldNotPostRunnable() =
- testComponent.runTest {
+ testScope.runTest {
// GIVEN shade is open and detector is enabled
- shadeRepository.setLegacyShadeExpansion(1f)
+ shadeTestUtil.setShadeExpansion(1f)
detector.enable(action)
runCurrent()
// WHEN shade begins to collapse
- shadeRepository.setLegacyShadeExpansion(.5f)
+ shadeTestUtil.programmaticCollapseShade()
runCurrent()
// THEN action not run
verifyZeroInteractions(action)
+ detector.disable()
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModelTest.kt
index b05d959..f62a55d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModelTest.kt
@@ -22,7 +22,6 @@
import android.view.View
import android.view.View.GONE
import android.view.View.VISIBLE
-import android.widget.LinearLayout
import androidx.test.filters.SmallTest
import com.android.internal.logging.UiEventLogger
import com.android.settingslib.bluetooth.CachedBluetoothDevice
@@ -30,6 +29,7 @@
import com.android.settingslib.flags.Flags
import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.DialogTransitionAnimator
+import com.android.systemui.animation.Expandable
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.statusbar.phone.SystemUIDialog
import com.android.systemui.util.FakeSharedPreferences
@@ -77,6 +77,8 @@
@Mock private lateinit var deviceItemInteractor: DeviceItemInteractor
+ @Mock private lateinit var deviceItemActionInteractor: DeviceItemActionInteractor
+
@Mock private lateinit var activityStarter: ActivityStarter
@Mock private lateinit var mDialogTransitionAnimator: DialogTransitionAnimator
@@ -100,6 +102,8 @@
@Mock private lateinit var bluetoothTileDialogDelegate: BluetoothTileDialogDelegate
@Mock private lateinit var sysuiDialog: SystemUIDialog
+ @Mock private lateinit var expandable: Expandable
+ @Mock private lateinit var controller: DialogTransitionAnimator.Controller
private val sharedPreferences = FakeSharedPreferences()
@@ -116,6 +120,7 @@
bluetoothTileDialogViewModel =
BluetoothTileDialogViewModel(
deviceItemInteractor,
+ deviceItemActionInteractor,
BluetoothStateInteractor(
localBluetoothManager,
bluetoothTileDialogLogger,
@@ -157,6 +162,7 @@
.thenReturn(getMutableStateFlow(false))
whenever(audioSharingInteractor.audioSharingButtonStateUpdate)
.thenReturn(getMutableStateFlow(AudioSharingButtonState.Gone))
+ whenever(expandable.dialogTransitionController(any())).thenReturn(controller)
}
@Test
@@ -164,16 +170,16 @@
testScope.runTest {
bluetoothTileDialogViewModel.showDialog(null)
- verify(mDialogTransitionAnimator, never()).showFromView(any(), any(), any(), any())
+ verify(mDialogTransitionAnimator, never()).show(any(), any(), any())
}
}
@Test
fun testShowDialog_animated() {
testScope.runTest {
- bluetoothTileDialogViewModel.showDialog(LinearLayout(mContext))
+ bluetoothTileDialogViewModel.showDialog(expandable)
- verify(mDialogTransitionAnimator).showFromView(any(), any(), nullable(), anyBoolean())
+ verify(mDialogTransitionAnimator).show(any(), any(), anyBoolean())
}
}
@@ -181,10 +187,9 @@
fun testShowDialog_animated_callInBackgroundThread() {
testScope.runTest {
backgroundExecutor.execute {
- bluetoothTileDialogViewModel.showDialog(LinearLayout(mContext))
+ bluetoothTileDialogViewModel.showDialog(expandable)
- verify(mDialogTransitionAnimator)
- .showFromView(any(), any(), nullable(), anyBoolean())
+ verify(mDialogTransitionAnimator).show(any(), any(), anyBoolean())
}
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/DeviceItemActionInteractorImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/DeviceItemActionInteractorImplTest.kt
new file mode 100644
index 0000000..762137b
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/DeviceItemActionInteractorImplTest.kt
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.bluetooth.qsdialog
+
+import android.bluetooth.BluetoothDevice
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import androidx.test.filters.SmallTest
+import com.android.settingslib.bluetooth.CachedBluetoothDevice
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.kosmos.testDispatcher
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.statusbar.phone.SystemUIDialog
+import com.android.systemui.testKosmos
+import com.android.systemui.util.mockito.whenever
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.junit.MockitoJUnit
+import org.mockito.junit.MockitoRule
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+@OptIn(ExperimentalCoroutinesApi::class)
+class DeviceItemActionInteractorImplTest : SysuiTestCase() {
+ @get:Rule val mockitoRule: MockitoRule = MockitoJUnit.rule()
+ private val kosmos = testKosmos().apply { testDispatcher = UnconfinedTestDispatcher() }
+ private lateinit var actionInteractorImpl: DeviceItemActionInteractor
+
+ @Mock private lateinit var dialog: SystemUIDialog
+ @Mock private lateinit var cachedDevice: CachedBluetoothDevice
+ @Mock private lateinit var device: BluetoothDevice
+ @Mock private lateinit var deviceItem: DeviceItem
+
+ @Before
+ fun setUp() {
+ actionInteractorImpl = kosmos.deviceItemActionInteractor
+ whenever(deviceItem.cachedBluetoothDevice).thenReturn(cachedDevice)
+ whenever(cachedDevice.address).thenReturn("ADDRESS")
+ whenever(cachedDevice.device).thenReturn(device)
+ }
+
+ @Test
+ fun testOnClick_connectedMedia_setActive() {
+ with(kosmos) {
+ testScope.runTest {
+ whenever(deviceItem.type)
+ .thenReturn(DeviceItemType.AVAILABLE_MEDIA_BLUETOOTH_DEVICE)
+ actionInteractorImpl.onClick(deviceItem, dialog)
+ verify(cachedDevice).setActive()
+ verify(bluetoothTileDialogLogger)
+ .logDeviceClick(
+ cachedDevice.address,
+ DeviceItemType.AVAILABLE_MEDIA_BLUETOOTH_DEVICE
+ )
+ }
+ }
+ }
+
+ @Test
+ fun testOnClick_activeMedia_disconnect() {
+ with(kosmos) {
+ testScope.runTest {
+ whenever(deviceItem.type).thenReturn(DeviceItemType.ACTIVE_MEDIA_BLUETOOTH_DEVICE)
+ actionInteractorImpl.onClick(deviceItem, dialog)
+ verify(cachedDevice).disconnect()
+ verify(bluetoothTileDialogLogger)
+ .logDeviceClick(
+ cachedDevice.address,
+ DeviceItemType.ACTIVE_MEDIA_BLUETOOTH_DEVICE
+ )
+ }
+ }
+ }
+
+ @Test
+ fun testOnClick_connectedOtherDevice_disconnect() {
+ with(kosmos) {
+ testScope.runTest {
+ whenever(deviceItem.type).thenReturn(DeviceItemType.CONNECTED_BLUETOOTH_DEVICE)
+ actionInteractorImpl.onClick(deviceItem, dialog)
+ verify(cachedDevice).disconnect()
+ verify(bluetoothTileDialogLogger)
+ .logDeviceClick(cachedDevice.address, DeviceItemType.CONNECTED_BLUETOOTH_DEVICE)
+ }
+ }
+ }
+
+ @Test
+ fun testOnClick_saved_connect() {
+ with(kosmos) {
+ testScope.runTest {
+ whenever(deviceItem.type).thenReturn(DeviceItemType.SAVED_BLUETOOTH_DEVICE)
+ actionInteractorImpl.onClick(deviceItem, dialog)
+ verify(cachedDevice).connect()
+ verify(bluetoothTileDialogLogger)
+ .logDeviceClick(cachedDevice.address, DeviceItemType.SAVED_BLUETOOTH_DEVICE)
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/DeviceItemActionInteractorKosmos.kt b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/DeviceItemActionInteractorKosmos.kt
new file mode 100644
index 0000000..e8e37bc
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/DeviceItemActionInteractorKosmos.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.bluetooth.qsdialog
+
+import com.android.internal.logging.uiEventLogger
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.testDispatcher
+import com.android.systemui.util.mockito.mock
+
+val Kosmos.bluetoothTileDialogLogger: BluetoothTileDialogLogger by Kosmos.Fixture { mock {} }
+
+val Kosmos.deviceItemActionInteractor: DeviceItemActionInteractor by
+ Kosmos.Fixture {
+ DeviceItemActionInteractorImpl(
+ testDispatcher,
+ bluetoothTileDialogLogger,
+ uiEventLogger,
+ )
+ }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractorTest.kt
index daf4a3c..2b4f950 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractorTest.kt
@@ -23,7 +23,6 @@
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import androidx.test.filters.SmallTest
-import com.android.internal.logging.UiEventLogger
import com.android.settingslib.bluetooth.CachedBluetoothDevice
import com.android.settingslib.bluetooth.LocalBluetoothManager
import com.android.systemui.SysuiTestCase
@@ -39,7 +38,6 @@
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
-import org.mockito.Mockito.verify
import org.mockito.Mockito.`when`
import org.mockito.junit.MockitoJUnit
import org.mockito.junit.MockitoRule
@@ -71,8 +69,6 @@
@Mock private lateinit var localBluetoothManager: LocalBluetoothManager
- @Mock private lateinit var uiEventLogger: UiEventLogger
-
@Mock private lateinit var logger: BluetoothTileDialogLogger
private val fakeSystemClock = FakeSystemClock()
@@ -94,7 +90,6 @@
adapter,
localBluetoothManager,
fakeSystemClock,
- uiEventLogger,
logger,
testScope.backgroundScope,
dispatcher
@@ -218,61 +213,6 @@
}
}
- @Test
- fun testUpdateDeviceItemOnClick_connectedMedia_setActive() {
- testScope.runTest {
- `when`(deviceItem1.type).thenReturn(DeviceItemType.AVAILABLE_MEDIA_BLUETOOTH_DEVICE)
-
- interactor.updateDeviceItemOnClick(deviceItem1)
-
- verify(cachedDevice1).setActive()
- verify(logger)
- .logDeviceClick(
- cachedDevice1.address,
- DeviceItemType.AVAILABLE_MEDIA_BLUETOOTH_DEVICE
- )
- }
- }
-
- @Test
- fun testUpdateDeviceItemOnClick_activeMedia_disconnect() {
- testScope.runTest {
- `when`(deviceItem1.type).thenReturn(DeviceItemType.ACTIVE_MEDIA_BLUETOOTH_DEVICE)
-
- interactor.updateDeviceItemOnClick(deviceItem1)
-
- verify(cachedDevice1).disconnect()
- verify(logger)
- .logDeviceClick(cachedDevice1.address, DeviceItemType.ACTIVE_MEDIA_BLUETOOTH_DEVICE)
- }
- }
-
- @Test
- fun testUpdateDeviceItemOnClick_connectedOtherDevice_disconnect() {
- testScope.runTest {
- `when`(deviceItem1.type).thenReturn(DeviceItemType.CONNECTED_BLUETOOTH_DEVICE)
-
- interactor.updateDeviceItemOnClick(deviceItem1)
-
- verify(cachedDevice1).disconnect()
- verify(logger)
- .logDeviceClick(cachedDevice1.address, DeviceItemType.CONNECTED_BLUETOOTH_DEVICE)
- }
- }
-
- @Test
- fun testUpdateDeviceItemOnClick_saved_connect() {
- testScope.runTest {
- `when`(deviceItem1.type).thenReturn(DeviceItemType.SAVED_BLUETOOTH_DEVICE)
-
- interactor.updateDeviceItemOnClick(deviceItem1)
-
- verify(cachedDevice1).connect()
- verify(logger)
- .logDeviceClick(cachedDevice1.address, DeviceItemType.SAVED_BLUETOOTH_DEVICE)
- }
- }
-
private fun createFactory(
isFilterMatchFunc: (CachedBluetoothDevice) -> Boolean,
deviceItem: DeviceItem
diff --git a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractorTest.kt
index 43c860c..2b7e7ad 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractorTest.kt
@@ -29,7 +29,7 @@
import com.android.systemui.keyguard.data.repository.deviceEntryFingerprintAuthRepository
import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFaceAuthRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
-import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
+import com.android.systemui.keyguard.shared.model.BiometricUnlockMode
import com.android.systemui.keyguard.shared.model.BiometricUnlockSource
import com.android.systemui.keyguard.shared.model.FailFingerprintAuthenticationStatus
import com.android.systemui.kosmos.testScope
@@ -162,7 +162,7 @@
kosmos.fakeKeyguardRepository.setBiometricUnlockSource(
BiometricUnlockSource.FINGERPRINT_SENSOR
)
- kosmos.fakeKeyguardRepository.setBiometricUnlockState(BiometricUnlockModel.WAKE_AND_UNLOCK)
+ kosmos.fakeKeyguardRepository.setBiometricUnlockState(BiometricUnlockMode.WAKE_AND_UNLOCK)
}
private fun fingerprintFailure() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyboard/shortcut/ui/ShortcutHelperActivityStarterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyboard/shortcut/ui/ShortcutHelperActivityStarterTest.kt
new file mode 100644
index 0000000..05a2ca2
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyboard/shortcut/ui/ShortcutHelperActivityStarterTest.kt
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyboard.shortcut.ui
+
+import android.content.Intent
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.keyboard.shortcut.fakeShortcutHelperStartActivity
+import com.android.systemui.keyboard.shortcut.shortcutHelperActivityStarter
+import com.android.systemui.keyboard.shortcut.shortcutHelperTestHelper
+import com.android.systemui.keyboard.shortcut.ui.view.ShortcutHelperActivity
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.testCase
+import com.android.systemui.kosmos.testDispatcher
+import com.android.systemui.kosmos.testScope
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(JUnit4::class)
+class ShortcutHelperActivityStarterTest : SysuiTestCase() {
+
+ private val kosmos =
+ Kosmos().also {
+ it.testCase = this
+ it.testDispatcher = UnconfinedTestDispatcher()
+ }
+
+ private val testScope = kosmos.testScope
+ private val testHelper = kosmos.shortcutHelperTestHelper
+ private val fakeStartActivity = kosmos.fakeShortcutHelperStartActivity
+ private val starter = kosmos.shortcutHelperActivityStarter
+
+ @Test
+ fun start_doesNotStartByDefault() =
+ testScope.runTest {
+ starter.start()
+
+ assertThat(fakeStartActivity.startIntents).isEmpty()
+ }
+
+ @Test
+ fun start_onToggle_startsActivity() =
+ testScope.runTest {
+ starter.start()
+
+ testHelper.toggle(deviceId = 456)
+
+ verifyShortcutHelperActivityStarted()
+ }
+
+ @Test
+ fun start_onToggle_multipleTimesStartsActivityOnlyWhenNotStarted() =
+ testScope.runTest {
+ starter.start()
+
+ testHelper.toggle(deviceId = 456)
+ testHelper.toggle(deviceId = 456)
+ testHelper.toggle(deviceId = 456)
+ testHelper.toggle(deviceId = 456)
+
+ verifyShortcutHelperActivityStarted(numTimes = 2)
+ }
+
+ @Test
+ fun start_onRequestShowShortcuts_startsActivity() =
+ testScope.runTest {
+ starter.start()
+
+ testHelper.showFromActivity()
+
+ verifyShortcutHelperActivityStarted()
+ }
+
+ @Test
+ fun start_onRequestShowShortcuts_multipleTimes_startsActivityOnlyOnce() =
+ testScope.runTest {
+ starter.start()
+
+ testHelper.showFromActivity()
+ testHelper.showFromActivity()
+ testHelper.showFromActivity()
+
+ verifyShortcutHelperActivityStarted(numTimes = 1)
+ }
+
+ @Test
+ fun start_onRequestShowShortcuts_multipleTimes_startsActivityOnlyWhenNotStarted() =
+ testScope.runTest {
+ starter.start()
+
+ testHelper.hideFromActivity()
+ testHelper.hideForSystem()
+ testHelper.toggle(deviceId = 987)
+ testHelper.showFromActivity()
+ testHelper.hideFromActivity()
+ testHelper.hideForSystem()
+ testHelper.toggle(deviceId = 456)
+ testHelper.showFromActivity()
+
+ verifyShortcutHelperActivityStarted(numTimes = 2)
+ }
+
+ private fun verifyShortcutHelperActivityStarted(numTimes: Int = 1) {
+ assertThat(fakeStartActivity.startIntents).hasSize(numTimes)
+ fakeStartActivity.startIntents.forEach { intent ->
+ assertThat(intent.flags).isEqualTo(Intent.FLAG_ACTIVITY_NEW_TASK)
+ assertThat(intent.filterEquals(Intent(context, ShortcutHelperActivity::class.java)))
+ .isTrue()
+ }
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutHelperViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutHelperViewModelTest.kt
new file mode 100644
index 0000000..8653308
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutHelperViewModelTest.kt
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyboard.shortcut.ui.viewmodel
+
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.coroutines.collectValues
+import com.android.systemui.keyboard.shortcut.shortcutHelperTestHelper
+import com.android.systemui.keyboard.shortcut.shortcutHelperViewModel
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.testCase
+import com.android.systemui.kosmos.testDispatcher
+import com.android.systemui.kosmos.testScope
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(JUnit4::class)
+class ShortcutHelperViewModelTest : SysuiTestCase() {
+
+ private val kosmos =
+ Kosmos().also {
+ it.testCase = this
+ it.testDispatcher = UnconfinedTestDispatcher()
+ }
+
+ private val testScope = kosmos.testScope
+ private val testHelper = kosmos.shortcutHelperTestHelper
+
+ private val viewModel = kosmos.shortcutHelperViewModel
+
+ @Test
+ fun shouldShow_falseByDefault() =
+ testScope.runTest {
+ val shouldShow by collectLastValue(viewModel.shouldShow)
+
+ assertThat(shouldShow).isFalse()
+ }
+
+ @Test
+ fun shouldShow_trueAfterShowRequested() =
+ testScope.runTest {
+ val shouldShow by collectLastValue(viewModel.shouldShow)
+
+ testHelper.showFromActivity()
+
+ assertThat(shouldShow).isTrue()
+ }
+
+ @Test
+ fun shouldShow_trueAfterToggleRequested() =
+ testScope.runTest {
+ val shouldShow by collectLastValue(viewModel.shouldShow)
+
+ testHelper.toggle(deviceId = 123)
+
+ assertThat(shouldShow).isTrue()
+ }
+
+ @Test
+ fun shouldShow_falseAfterToggleTwice() =
+ testScope.runTest {
+ val shouldShow by collectLastValue(viewModel.shouldShow)
+
+ testHelper.toggle(deviceId = 123)
+ testHelper.toggle(deviceId = 123)
+
+ assertThat(shouldShow).isFalse()
+ }
+
+ @Test
+ fun shouldShow_falseAfterViewDestroyed() =
+ testScope.runTest {
+ val shouldShow by collectLastValue(viewModel.shouldShow)
+
+ testHelper.toggle(deviceId = 567)
+ viewModel.onUserLeave()
+
+ assertThat(shouldShow).isFalse()
+ }
+
+ @Test
+ fun shouldShow_doesNotEmitDuplicateValues() =
+ testScope.runTest {
+ val shouldShowValues by collectValues(viewModel.shouldShow)
+
+ testHelper.hideForSystem()
+ testHelper.toggle(deviceId = 987)
+ testHelper.showFromActivity()
+ viewModel.onUserLeave()
+ testHelper.hideFromActivity()
+ testHelper.hideForSystem()
+ testHelper.toggle(deviceId = 456)
+ testHelper.showFromActivity()
+
+ assertThat(shouldShowValues).containsExactly(false, true, false, true).inOrder()
+ }
+
+ @Test
+ fun shouldShow_emitsLatestValueToNewSubscribers() =
+ testScope.runTest {
+ val shouldShow by collectLastValue(viewModel.shouldShow)
+
+ testHelper.showFromActivity()
+
+ val shouldShowNew by collectLastValue(viewModel.shouldShow)
+ assertThat(shouldShowNew).isEqualTo(shouldShow)
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewControllerTest.java
index 39fcd41..5b836b6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewControllerTest.java
@@ -346,6 +346,24 @@
}
@Test
+ public void testStartDozing_withMinShowTime() {
+ // GIVEN a biometric message is showing
+ mController.updateIndication(INDICATION_TYPE_BIOMETRIC_MESSAGE,
+ new KeyguardIndication.Builder()
+ .setMessage("test_message")
+ .setMinVisibilityMillis(5000L)
+ .setTextColor(ColorStateList.valueOf(Color.WHITE))
+ .build(),
+ true);
+
+ // WHEN the device wants to hide the biometric message
+ mController.hideIndication(INDICATION_TYPE_BIOMETRIC_MESSAGE);
+
+ // THEN switch to INDICATION_TYPE_NONE
+ verify(mView).switchIndication(null);
+ }
+
+ @Test
public void testStoppedDozing() {
// GIVEN we're dozing & we have an indication message
mStatusBarStateListener.onDozingChanged(true);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
index 325e7bf..6b1d39a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -241,7 +241,7 @@
.thenReturn(mock(Flow.class));
when(mDreamViewModel.getTransitionEnded())
.thenReturn(mock(Flow.class));
- when(mCommunalTransitionViewModel.getShowByDefault())
+ when(mCommunalTransitionViewModel.getShowCommunalFromOccluded())
.thenReturn(mock(Flow.class));
when(mCommunalTransitionViewModel.getTransitionFromOccludedEnded())
.thenReturn(mock(Flow.class));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardSmartspaceRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardSmartspaceRepositoryImplTest.kt
new file mode 100644
index 0000000..a320845
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardSmartspaceRepositoryImplTest.kt
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.data.repository
+
+import android.provider.Settings
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.settings.FakeUserTracker
+import com.android.systemui.util.settings.FakeSettings
+import com.google.common.truth.Truth
+import kotlin.test.Test
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestCoroutineScheduler
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.MockitoAnnotations
+
+@RunWith(JUnit4::class)
+@SmallTest
+class KeyguardSmartspaceRepositoryImplTest : SysuiTestCase() {
+
+ private lateinit var scheduler: TestCoroutineScheduler
+ private lateinit var dispatcher: CoroutineDispatcher
+ private lateinit var scope: TestScope
+
+ private lateinit var underTest: KeyguardSmartspaceRepository
+ private lateinit var fakeSettings: FakeSettings
+ private lateinit var fakeUserTracker: FakeUserTracker
+
+ @Before
+ fun setup() {
+ MockitoAnnotations.initMocks(this)
+ fakeSettings = FakeSettings()
+ fakeUserTracker = FakeUserTracker()
+ fakeSettings.userId = fakeUserTracker.userId
+ scheduler = TestCoroutineScheduler()
+ dispatcher = StandardTestDispatcher(scheduler)
+ scope = TestScope(dispatcher)
+ underTest =
+ KeyguardSmartspaceRepositoryImpl(
+ context = context,
+ secureSettings = fakeSettings,
+ userTracker = fakeUserTracker,
+ applicationScope = scope.backgroundScope,
+ )
+ }
+
+ @Test
+ fun testWeatherEnabled_true() =
+ scope.runTest {
+ fakeSettings.putInt(Settings.Secure.LOCK_SCREEN_WEATHER_ENABLED, 1)
+ val value = collectLastValue(underTest.isWeatherEnabled)
+ Truth.assertThat(value()).isEqualTo(true)
+ }
+
+ @Test
+ fun testWeatherEnabled_false() =
+ scope.runTest {
+ fakeSettings.putInt(Settings.Secure.LOCK_SCREEN_WEATHER_ENABLED, 0)
+
+ val value = collectLastValue(underTest.isWeatherEnabled)
+ Truth.assertThat(value()).isEqualTo(false)
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractorTest.kt
index cded2a4..593cfde 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractorTest.kt
@@ -45,8 +45,7 @@
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
import com.android.systemui.keyguard.data.repository.keyguardOcclusionRepository
-import com.android.systemui.keyguard.data.repository.keyguardRepository
-import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
+import com.android.systemui.keyguard.shared.model.BiometricUnlockMode
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.util.KeyguardTransitionRepositorySpySubject.Companion.assertThat
@@ -99,7 +98,7 @@
to = KeyguardState.DOZING,
testScope
)
- kosmos.keyguardRepository.setBiometricUnlockState(BiometricUnlockModel.NONE)
+ kosmos.fakeKeyguardRepository.setBiometricUnlockState(BiometricUnlockMode.NONE)
reset(transitionRepository)
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractorTest.kt
index 8435a03..7c92ede 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractorTest.kt
@@ -42,8 +42,7 @@
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
import com.android.systemui.keyguard.data.repository.keyguardOcclusionRepository
-import com.android.systemui.keyguard.data.repository.keyguardRepository
-import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
+import com.android.systemui.keyguard.shared.model.BiometricUnlockMode
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.util.KeyguardTransitionRepositorySpySubject.Companion.assertThat
import com.android.systemui.kosmos.testScope
@@ -87,7 +86,7 @@
to = KeyguardState.DREAMING,
testScope
)
- kosmos.keyguardRepository.setBiometricUnlockState(BiometricUnlockModel.NONE)
+ kosmos.fakeKeyguardRepository.setBiometricUnlockState(BiometricUnlockMode.NONE)
reset(transitionRepository)
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardSurfaceBehindInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardSurfaceBehindInteractorTest.kt
index 9ccf212..f32e775 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardSurfaceBehindInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardSurfaceBehindInteractorTest.kt
@@ -274,4 +274,27 @@
runCurrent()
assertThat(isAnimatingSurface).isFalse()
}
+
+ @Test
+ fun notificationLaunchFalse_isAnimatingSurfaceFalse() =
+ testScope.runTest {
+ val isAnimatingSurface by collectLastValue(underTest.isAnimatingSurface)
+ transitionRepository.sendTransitionStep(
+ TransitionStep(
+ from = KeyguardState.AOD,
+ to = KeyguardState.LOCKSCREEN,
+ transitionState = TransitionState.STARTED,
+ )
+ )
+ transitionRepository.sendTransitionStep(
+ TransitionStep(
+ from = KeyguardState.AOD,
+ to = KeyguardState.LOCKSCREEN,
+ transitionState = TransitionState.FINISHED,
+ )
+ )
+ kosmos.notificationLaunchAnimationInteractor.setIsLaunchAnimationRunning(false)
+ runCurrent()
+ assertThat(isAnimatingSurface).isFalse()
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
index 3827046..1dc58d1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
@@ -26,15 +26,15 @@
import com.android.systemui.SysuiTestCase
import com.android.systemui.bouncer.data.repository.fakeKeyguardBouncerRepository
import com.android.systemui.communal.domain.interactor.communalInteractor
+import com.android.systemui.communal.domain.interactor.setCommunalAvailable
import com.android.systemui.communal.shared.model.CommunalScenes
-import com.android.systemui.dock.DockManager
import com.android.systemui.dock.fakeDockManager
import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
import com.android.systemui.keyguard.data.repository.fakeCommandQueue
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
-import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
+import com.android.systemui.keyguard.shared.model.BiometricUnlockMode
import com.android.systemui.keyguard.shared.model.DozeStateModel
import com.android.systemui.keyguard.shared.model.DozeTransitionModel
import com.android.systemui.keyguard.shared.model.KeyguardState
@@ -358,7 +358,7 @@
// WHEN biometrics succeeds with wake and unlock from dream mode
keyguardRepository.setBiometricUnlockState(
- BiometricUnlockModel.WAKE_AND_UNLOCK_FROM_DREAM
+ BiometricUnlockMode.WAKE_AND_UNLOCK_FROM_DREAM
)
runCurrent()
@@ -535,7 +535,7 @@
// WHEN biometrics succeeds with wake and unlock mode
powerInteractor.setAwakeForTest()
- keyguardRepository.setBiometricUnlockState(BiometricUnlockModel.WAKE_AND_UNLOCK)
+ keyguardRepository.setBiometricUnlockState(BiometricUnlockMode.WAKE_AND_UNLOCK)
advanceTimeBy(60L)
assertThat(transitionRepository)
@@ -1229,23 +1229,22 @@
}
@Test
- fun occludedToGlanceableHubWhenDocked() =
+ fun occludedToGlanceableHubWhenInitiallyOnHub() =
testScope.runTest {
- // GIVEN a device on lockscreen
+ // GIVEN a device on lockscreen and communal is available
keyguardRepository.setKeyguardShowing(true)
+ kosmos.setCommunalAvailable(true)
runCurrent()
- // GIVEN a prior transition has run to OCCLUDED
+ // GIVEN a prior transition has run to OCCLUDED from GLANCEABLE_HUB
runTransitionAndSetWakefulness(KeyguardState.GLANCEABLE_HUB, KeyguardState.OCCLUDED)
keyguardRepository.setKeyguardOccluded(true)
runCurrent()
- // GIVEN device is docked/communal is available
- dockManager.setIsDocked(true)
- dockManager.setDockEvent(DockManager.STATE_DOCKED)
+ // GIVEN on blank scene
val idleTransitionState =
MutableStateFlow<ObservableTransitionState>(
- ObservableTransitionState.Idle(CommunalScenes.Communal)
+ ObservableTransitionState.Idle(CommunalScenes.Blank)
)
communalInteractor.setTransitionState(idleTransitionState)
runCurrent()
@@ -1463,6 +1462,7 @@
ObservableTransitionState.Transition(
fromScene = currentScene,
toScene = targetScene,
+ currentScene = flowOf(targetScene),
progress = progress,
isInitiatedByUserInput = false,
isUserInputOngoing = flowOf(false),
@@ -1645,6 +1645,7 @@
ObservableTransitionState.Transition(
fromScene = currentScene,
toScene = targetScene,
+ currentScene = flowOf(targetScene),
progress = progress,
isInitiatedByUserInput = false,
isUserInputOngoing = flowOf(false),
@@ -1701,6 +1702,7 @@
ObservableTransitionState.Transition(
fromScene = currentScene,
toScene = targetScene,
+ currentScene = flowOf(targetScene),
progress = progress,
isInitiatedByUserInput = false,
isUserInputOngoing = flowOf(false),
@@ -1874,6 +1876,7 @@
ObservableTransitionState.Transition(
fromScene = currentScene,
toScene = targetScene,
+ currentScene = flowOf(targetScene),
progress = flowOf(0f, 0.1f),
isInitiatedByUserInput = false,
isUserInputOngoing = flowOf(false),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/SmartspaceSectionTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/SmartspaceSectionTest.kt
index 8eccde7..be10b82 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/SmartspaceSectionTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/SmartspaceSectionTest.kt
@@ -64,6 +64,7 @@
private val clockShouldBeCentered = MutableStateFlow(false)
private val hasCustomWeatherDataDisplay = MutableStateFlow(false)
+ private val isWeatherVisibleFlow = MutableStateFlow(false)
@Before
fun setup() {
@@ -89,7 +90,7 @@
.thenReturn(hasCustomWeatherDataDisplay)
whenever(keyguardClockViewModel.clockShouldBeCentered).thenReturn(clockShouldBeCentered)
whenever(keyguardSmartspaceViewModel.isSmartspaceEnabled).thenReturn(true)
-
+ whenever(keyguardSmartspaceViewModel.isWeatherVisible).thenReturn(isWeatherVisibleFlow)
constraintSet = ConstraintSet()
}
@@ -124,7 +125,6 @@
@Test
fun testConstraintsWhenNotHasCustomWeatherDataDisplay() {
whenever(keyguardSmartspaceViewModel.isDateWeatherDecoupled).thenReturn(true)
- hasCustomWeatherDataDisplay.value = false
underTest.addViews(constraintLayout)
underTest.applyConstraints(constraintSet)
assertWeatherSmartspaceConstrains(constraintSet)
@@ -149,13 +149,12 @@
@Test
fun testNormalDateWeatherVisibility() {
- hasCustomWeatherDataDisplay.value = false
- whenever(keyguardSmartspaceViewModel.isWeatherEnabled).thenReturn(true)
+ isWeatherVisibleFlow.value = true
underTest.addViews(constraintLayout)
underTest.applyConstraints(constraintSet)
assertThat(constraintSet.getVisibility(weatherView.id)).isEqualTo(VISIBLE)
- whenever(keyguardSmartspaceViewModel.isWeatherEnabled).thenReturn(false)
+ isWeatherVisibleFlow.value = false
underTest.applyConstraints(constraintSet)
assertThat(constraintSet.getVisibility(weatherView.id)).isEqualTo(GONE)
assertThat(constraintSet.getVisibility(dateView.id)).isEqualTo(VISIBLE)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModelTest.kt
index 4bb0d47..0bca367 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModelTest.kt
@@ -26,7 +26,7 @@
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
-import com.android.systemui.keyguard.data.repository.keyguardRepository
+import com.android.systemui.keyguard.ui.view.DeviceEntryIconView
import com.android.systemui.keyguard.ui.viewmodel.DeviceEntryIconViewModel.Companion.UNLOCKED_DELAY_MS
import com.android.systemui.kosmos.testScope
import com.android.systemui.testKosmos
@@ -110,6 +110,46 @@
assertThat(isVisible).isTrue()
}
+ @Test
+ fun iconType_fingerprint() =
+ testScope.runTest {
+ val iconType by collectLastValue(underTest.iconType)
+ keyguardRepository.setKeyguardDismissible(false)
+ fingerprintPropertyRepository.supportsUdfps()
+ fingerprintAuthRepository.setIsRunning(true)
+ assertThat(iconType).isEqualTo(DeviceEntryIconView.IconType.FINGERPRINT)
+ }
+
+ @Test
+ fun iconType_locked() =
+ testScope.runTest {
+ val iconType by collectLastValue(underTest.iconType)
+ keyguardRepository.setKeyguardDismissible(false)
+ fingerprintAuthRepository.setIsRunning(false)
+ assertThat(iconType).isEqualTo(DeviceEntryIconView.IconType.LOCK)
+ }
+
+ @Test
+ fun iconType_unlocked() =
+ testScope.runTest {
+ val iconType by collectLastValue(underTest.iconType)
+ keyguardRepository.setKeyguardDismissible(true)
+ advanceTimeBy(UNLOCKED_DELAY_MS * 2) // wait for unlocked delay
+ fingerprintAuthRepository.setIsRunning(false)
+ assertThat(iconType).isEqualTo(DeviceEntryIconView.IconType.UNLOCK)
+ }
+
+ @Test
+ fun iconType_none() =
+ testScope.runTest {
+ val iconType by collectLastValue(underTest.iconType)
+ keyguardRepository.setKeyguardDismissible(true)
+ advanceTimeBy(UNLOCKED_DELAY_MS * 2) // wait for unlocked delay
+ fingerprintPropertyRepository.supportsUdfps()
+ fingerprintAuthRepository.setIsRunning(true)
+ assertThat(iconType).isEqualTo(DeviceEntryIconView.IconType.NONE)
+ }
+
private fun deviceEntryIconTransitionAlpha(alpha: Float) {
deviceEntryIconTransition.setDeviceEntryParentViewAlpha(alpha)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardSmartspaceViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardSmartspaceViewModelTest.kt
new file mode 100644
index 0000000..78f4dcc
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardSmartspaceViewModelTest.kt
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.ui.viewmodel
+
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.keyguard.data.repository.fakeKeyguardClockRepository
+import com.android.systemui.keyguard.data.repository.keyguardClockRepository
+import com.android.systemui.keyguard.data.repository.keyguardSmartspaceRepository
+import com.android.systemui.keyguard.shared.model.ClockSize
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.plugins.clocks.ClockController
+import com.android.systemui.testKosmos
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.Answers
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(JUnit4::class)
+class KeyguardSmartspaceViewModelTest : SysuiTestCase() {
+ val kosmos = testKosmos()
+ val testScope = kosmos.testScope
+ val underTest = kosmos.keyguardSmartspaceViewModel
+ val res = context.resources
+
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS) private lateinit var clockController: ClockController
+
+ @Before
+ fun setup() {
+ MockitoAnnotations.initMocks(this)
+ kosmos.fakeKeyguardClockRepository.setCurrentClock(clockController)
+ }
+
+ @Test
+ fun testWhenWeatherEnabled_notCustomWeatherDataDisplay_isWeatherVisible_shouldBeTrue() =
+ testScope.runTest {
+ val isWeatherVisible by collectLastValue(underTest.isWeatherVisible)
+ whenever(clockController.largeClock.config.hasCustomWeatherDataDisplay)
+ .thenReturn(false)
+
+ with(kosmos) {
+ keyguardSmartspaceRepository.setIsWeatherEnabled(true)
+ keyguardClockRepository.setClockSize(ClockSize.LARGE)
+ }
+
+ assertThat(isWeatherVisible).isEqualTo(true)
+ }
+
+ @Test
+ fun testWhenWeatherEnabled_hasCustomWeatherDataDisplay_isWeatherVisible_shouldBeFalse() =
+ testScope.runTest {
+ val isWeatherVisible by collectLastValue(underTest.isWeatherVisible)
+ whenever(clockController.largeClock.config.hasCustomWeatherDataDisplay).thenReturn(true)
+
+ with(kosmos) {
+ keyguardSmartspaceRepository.setIsWeatherEnabled(true)
+ keyguardClockRepository.setClockSize(ClockSize.LARGE)
+ }
+
+ assertThat(isWeatherVisible).isEqualTo(false)
+ }
+
+ @Test
+ fun testWhenWeatherEnabled_notCustomWeatherDataDisplay_notIsWeatherVisible_shouldBeFalse() =
+ testScope.runTest {
+ val isWeatherVisible by collectLastValue(underTest.isWeatherVisible)
+ whenever(clockController.largeClock.config.hasCustomWeatherDataDisplay)
+ .thenReturn(false)
+
+ with(kosmos) {
+ keyguardSmartspaceRepository.setIsWeatherEnabled(false)
+ keyguardClockRepository.setClockSize(ClockSize.LARGE)
+ }
+
+ assertThat(isWeatherVisible).isEqualTo(false)
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java b/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java
index 9429725..b95d3aa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java
@@ -44,7 +44,6 @@
import android.os.UserHandle;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
-import android.view.View;
import androidx.test.filters.SmallTest;
@@ -53,6 +52,7 @@
import com.android.settingslib.fuelgauge.BatterySaverUtils;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.animation.DialogTransitionAnimator;
+import com.android.systemui.animation.Expandable;
import com.android.systemui.broadcast.BroadcastSender;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.settings.UserTracker;
@@ -88,7 +88,9 @@
@Mock
private UserTracker mUserTracker;
@Mock
- private View mView;
+ private Expandable mExpandable;
+ @Mock
+ private DialogTransitionAnimator.Controller mController;
@Mock
private SystemUIDialog.Factory mSystemUIDialogFactory;
@Mock
@@ -234,32 +236,31 @@
@Test
public void testDialogStartedFromLauncher_viewVisible() {
- when(mBatteryController.getLastPowerSaverStartView())
- .thenReturn(new WeakReference<>(mView));
- when(mView.isAggregatedVisible()).thenReturn(true);
+ when(mBatteryController.getLastPowerSaverStartExpandable())
+ .thenReturn(new WeakReference<>(mExpandable));
+ when(mExpandable.dialogTransitionController(any())).thenReturn(mController);
Intent intent = new Intent(BatterySaverUtils.ACTION_SHOW_START_SAVER_CONFIRMATION);
intent.putExtras(new Bundle());
mReceiver.onReceive(mContext, intent);
- verify(mDialogTransitionAnimator).showFromView(any(), eq(mView), any());
+ verify(mDialogTransitionAnimator).show(any(), eq(mController));
mPowerNotificationWarnings.getSaverConfirmationDialog().dismiss();
}
@Test
public void testDialogStartedNotFromLauncher_viewNotVisible() {
- when(mBatteryController.getLastPowerSaverStartView())
- .thenReturn(new WeakReference<>(mView));
- when(mView.isAggregatedVisible()).thenReturn(false);
+ when(mBatteryController.getLastPowerSaverStartExpandable())
+ .thenReturn(new WeakReference<>(mExpandable));
Intent intent = new Intent(BatterySaverUtils.ACTION_SHOW_START_SAVER_CONFIRMATION);
intent.putExtras(new Bundle());
mReceiver.onReceive(mContext, intent);
- verify(mDialogTransitionAnimator, never()).showFromView(any(), any());
+ verify(mDialogTransitionAnimator, never()).show(any(), any());
verify(mPowerNotificationWarnings.getSaverConfirmationDialog()).show();
mPowerNotificationWarnings.getSaverConfirmationDialog().dismiss();
@@ -267,7 +268,7 @@
@Test
public void testDialogShownNotFromLauncher() {
- when(mBatteryController.getLastPowerSaverStartView()).thenReturn(null);
+ when(mBatteryController.getLastPowerSaverStartExpandable()).thenReturn(null);
Intent intent = new Intent(BatterySaverUtils.ACTION_SHOW_START_SAVER_CONFIRMATION);
intent.putExtras(new Bundle());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
index ef7798e..5e14b1a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
@@ -43,7 +43,6 @@
import android.os.UserHandle;
import android.testing.AndroidTestingRunner;
import android.util.SparseArray;
-import android.view.View;
import androidx.annotation.Nullable;
import androidx.test.filters.SmallTest;
@@ -51,6 +50,7 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.util.CollectionUtils;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.animation.Expandable;
import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.dump.nano.SystemUIProtoDump;
import com.android.systemui.flags.FakeFeatureFlags;
@@ -734,7 +734,7 @@
}
@Override
- protected void handleClick(@Nullable View view) {}
+ protected void handleClick(@Nullable Expandable expandable) {}
@Override
protected void handleUpdateState(State state, Object arg) {}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
index df0ab34..8bf743884 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
@@ -44,13 +44,13 @@
import android.testing.TestableLooper;
import android.text.TextUtils;
import android.util.ArraySet;
-import android.view.View;
import androidx.annotation.Nullable;
import androidx.test.filters.SmallTest;
import com.android.internal.logging.InstanceId;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.animation.Expandable;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.qs.QSHost;
import com.android.systemui.res.R;
@@ -395,13 +395,13 @@
}
@Override
- public void click(@Nullable View view) {}
+ public void click(@Nullable Expandable expandable) {}
@Override
- public void secondaryClick(@Nullable View view) {}
+ public void secondaryClick(@Nullable Expandable expandable) {}
@Override
- public void longClick(@Nullable View view) {}
+ public void longClick(@Nullable Expandable expandable) {}
@Override
public void userSwitch(int currentUser) {}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt
index ef979d2..a8e9db5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt
@@ -35,11 +35,10 @@
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import android.view.IWindowManager
-import android.view.View
import com.android.internal.logging.MetricsLogger
import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.ActivityTransitionAnimator
-import com.android.systemui.animation.view.LaunchableFrameLayout
+import com.android.systemui.animation.Expandable
import com.android.systemui.classifier.FalsingManagerFake
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.plugins.qs.QSTile
@@ -339,7 +338,7 @@
tile.qsTile.activityLaunchForClick = pi
}
- tile.handleClick(mock(View::class.java))
+ tile.handleClick(mock(Expandable::class.java))
testableLooper.processAllMessages()
verify(activityStarter, never())
@@ -366,7 +365,7 @@
val tile = CustomTile.create(customTileFactory, TILE_SPEC, mContext)
tile.qsTile.activityLaunchForClick = pi
- tile.handleClick(mock(LaunchableFrameLayout::class.java))
+ tile.handleClick(mock(Expandable::class.java))
testableLooper.processAllMessages()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java
index 0a36ae6..f57f040 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java
@@ -15,6 +15,7 @@
*/
package com.android.systemui.qs.external;
+import static android.os.PowerExemptionManager.REASON_TILE_ONCLICK;
import static android.service.quicksettings.TileService.START_ACTIVITY_NEEDS_PENDING_INTENT;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
@@ -52,6 +53,7 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
+import android.os.IDeviceIdleController;
import android.os.UserHandle;
import android.service.quicksettings.IQSService;
import android.service.quicksettings.IQSTileService;
@@ -83,6 +85,7 @@
mock(BroadcastDispatcher.class);
private final IQSTileService.Stub mMockTileService = mock(IQSTileService.Stub.class);
private final ActivityManager mActivityManager = mock(ActivityManager.class);
+ private final IDeviceIdleController mDeviceIdleController = mock(IDeviceIdleController.class);
private ComponentName mTileServiceComponentName;
private Intent mTileServiceIntent;
@@ -126,6 +129,7 @@
mTileServiceIntent,
mUser,
mActivityManager,
+ mDeviceIdleController,
mExecutor);
}
@@ -386,6 +390,20 @@
}
@Test
+ public void testClickCallsDeviceIdleManager() throws Exception {
+ mStateManager.onTileAdded();
+ mStateManager.onStartListening();
+ mStateManager.onClick(null);
+ mStateManager.executeSetBindService(true);
+ mExecutor.runAllReady();
+
+ verify(mMockTileService).onClick(null);
+ verify(mDeviceIdleController).addPowerSaveTempWhitelistApp(
+ mTileServiceComponentName.getPackageName(), 15000,
+ mUser.getIdentifier(), REASON_TILE_ONCLICK, "tile onclick");
+ }
+
+ @Test
public void testFalseBindCallsUnbind() {
Context falseContext = mock(Context.class);
when(falseContext.bindServiceAsUser(any(), any(), anyInt(), any())).thenReturn(false);
@@ -396,6 +414,7 @@
mTileServiceIntent,
mUser,
mActivityManager,
+ mDeviceIdleController,
mExecutor);
manager.executeSetBindService(true);
@@ -418,6 +437,7 @@
mTileServiceIntent,
mUser,
mActivityManager,
+ mDeviceIdleController,
mExecutor);
manager.executeSetBindService(true);
@@ -440,6 +460,7 @@
mTileServiceIntent,
mUser,
mActivityManager,
+ mDeviceIdleController,
mExecutor);
manager.executeSetBindService(true);
@@ -464,6 +485,7 @@
mTileServiceIntent,
mUser,
mActivityManager,
+ mDeviceIdleController,
mExecutor);
manager.executeSetBindService(true);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/panels/ui/viewmodel/TileGridViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/panels/ui/viewmodel/TileGridViewModelTest.kt
deleted file mode 100644
index e8c5fd9..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/panels/ui/viewmodel/TileGridViewModelTest.kt
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.qs.panels.ui.viewmodel
-
-import android.testing.AndroidTestingRunner
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.kosmos.testScope
-import com.android.systemui.plugins.qs.QSTile
-import com.android.systemui.qs.FakeQSFactory
-import com.android.systemui.qs.pipeline.data.repository.tileSpecRepository
-import com.android.systemui.qs.pipeline.domain.interactor.FakeQSTile
-import com.android.systemui.qs.pipeline.shared.TileSpec
-import com.android.systemui.qs.qsTileFactory
-import com.android.systemui.testKosmos
-import kotlinx.coroutines.test.runTest
-import org.junit.Assert
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@SmallTest
-@RunWith(AndroidTestingRunner::class)
-class TileGridViewModelTest : SysuiTestCase() {
-
- private val kosmos = testKosmos().apply { qsTileFactory = FakeQSFactory(::tileCreator) }
- private val underTest = with(kosmos) { tileGridViewModel }
-
- @Test
- fun noIconTiles() =
- with(kosmos) {
- testScope.runTest {
- val latest by collectLastValue(underTest.tileViewModels)
-
- tileSpecRepository.setTiles(
- 0,
- listOf(
- TileSpec.create("bluetooth"),
- TileSpec.create("internet"),
- TileSpec.create("alarm")
- )
- )
-
- latest!!.forEach { Assert.assertFalse(it.iconOnly) }
- }
- }
-
- @Test
- fun withIconTiles() =
- with(kosmos) {
- testScope.runTest {
- val latest by collectLastValue(underTest.tileViewModels)
-
- tileSpecRepository.setTiles(
- 0,
- listOf(
- TileSpec.create("airplane"),
- TileSpec.create("flashlight"),
- TileSpec.create("rotation")
- )
- )
-
- latest!!.forEach { Assert.assertTrue(it.iconOnly) }
- }
- }
-
- private fun tileCreator(spec: String): QSTile {
- return FakeQSTile(0).apply { tileSpec = spec }
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
index 22b1c7b..c706244 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
@@ -51,7 +51,6 @@
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;
-import android.view.View;
import androidx.annotation.Nullable;
import androidx.test.filters.SmallTest;
@@ -63,6 +62,7 @@
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import com.android.systemui.InstanceIdSequenceFake;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.animation.Expandable;
import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.FalsingManager;
@@ -148,7 +148,7 @@
@Test
public void testClick_Metrics() {
- mTile.click(null /* view */);
+ mTile.click(null /* expandable */);
verify(mMetricsLogger).write(argThat(new TileLogMatcher(ACTION_QS_CLICK)));
assertEquals(1, mUiEventLoggerFake.numLogs());
UiEventLoggerFake.FakeUiEvent event = mUiEventLoggerFake.get(0);
@@ -159,7 +159,7 @@
public void testClick_log() {
when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE);
- mTile.click(null /* view */);
+ mTile.click(null /* expandable */);
verify(mQsLogger).logTileClick(eq(SPEC), eq(StatusBarState.SHADE), eq(Tile.STATE_ACTIVE),
anyInt());
}
@@ -184,7 +184,7 @@
@Test
public void testClick_Metrics_Status_Bar_Status() {
when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE);
- mTile.click(null /* view */);
+ mTile.click(null /* expandable */);
verify(mMetricsLogger).write(mLogCaptor.capture());
assertEquals(StatusBarState.SHADE, mLogCaptor.getValue()
.getTaggedData(FIELD_STATUS_BAR_STATE));
@@ -193,12 +193,12 @@
@Test
public void testClick_falsing() {
mFalsingManager.setFalseTap(true);
- mTile.click(null /* view */);
+ mTile.click(null /* expandable */);
mTestableLooper.processAllMessages();
assertThat(mTile.mClicked).isFalse();
mFalsingManager.setFalseTap(false);
- mTile.click(null /* view */);
+ mTile.click(null /* expandable */);
mTestableLooper.processAllMessages();
assertThat(mTile.mClicked).isTrue();
}
@@ -206,19 +206,19 @@
@Test
public void testLongClick_falsing() {
mFalsingManager.setFalseLongTap(true);
- mTile.longClick(null /* view */);
+ mTile.longClick(null /* expandable */);
mTestableLooper.processAllMessages();
assertThat(mTile.mLongClicked).isFalse();
mFalsingManager.setFalseLongTap(false);
- mTile.longClick(null /* view */);
+ mTile.longClick(null /* expandable */);
mTestableLooper.processAllMessages();
assertThat(mTile.mLongClicked).isTrue();
}
@Test
public void testSecondaryClick_Metrics() {
- mTile.secondaryClick(null /* view */);
+ mTile.secondaryClick(null /* expandable */);
verify(mMetricsLogger).write(argThat(new TileLogMatcher(ACTION_QS_SECONDARY_CLICK)));
assertEquals(1, mUiEventLoggerFake.numLogs());
UiEventLoggerFake.FakeUiEvent event = mUiEventLoggerFake.get(0);
@@ -229,7 +229,7 @@
public void testSecondaryClick_log() {
when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE);
- mTile.secondaryClick(null /* view */);
+ mTile.secondaryClick(null /* expandable */);
verify(mQsLogger).logTileSecondaryClick(eq(SPEC), eq(StatusBarState.SHADE),
eq(Tile.STATE_ACTIVE), anyInt());
}
@@ -254,7 +254,7 @@
@Test
public void testSecondaryClick_Metrics_Status_Bar_Status() {
when(mStatusBarStateController.getState()).thenReturn(StatusBarState.KEYGUARD);
- mTile.secondaryClick(null /* view */);
+ mTile.secondaryClick(null /* expandable */);
verify(mMetricsLogger).write(mLogCaptor.capture());
assertEquals(StatusBarState.KEYGUARD, mLogCaptor.getValue()
.getTaggedData(FIELD_STATUS_BAR_STATE));
@@ -262,7 +262,7 @@
@Test
public void testLongClick_Metrics() {
- mTile.longClick(null /* view */);
+ mTile.longClick(null /* expandable */);
verify(mMetricsLogger).write(argThat(new TileLogMatcher(ACTION_QS_LONG_PRESS)));
assertEquals(1, mUiEventLoggerFake.numLogs());
UiEventLoggerFake.FakeUiEvent event = mUiEventLoggerFake.get(0);
@@ -274,7 +274,7 @@
public void testLongClick_log() {
when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE);
- mTile.longClick(null /* view */);
+ mTile.longClick(null /* expandable */);
verify(mQsLogger).logTileLongClick(eq(SPEC), eq(StatusBarState.SHADE),
eq(Tile.STATE_ACTIVE), anyInt());
}
@@ -299,7 +299,7 @@
@Test
public void testLongClick_Metrics_Status_Bar_Status() {
when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE_LOCKED);
- mTile.click(null /* view */);
+ mTile.click(null /* expandable */);
verify(mMetricsLogger).write(mLogCaptor.capture());
assertEquals(StatusBarState.SHADE_LOCKED, mLogCaptor.getValue()
.getTaggedData(FIELD_STATUS_BAR_STATE));
@@ -560,12 +560,12 @@
}
@Override
- protected void handleClick(@Nullable View view) {
+ protected void handleClick(@Nullable Expandable expandable) {
mClicked = true;
}
@Override
- protected void handleLongClick(@Nullable View view) {
+ protected void handleLongClick(@Nullable Expandable expandable) {
mLongClicked = true;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileViewImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileViewImplTest.kt
index ecbd0f5..db11c3e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileViewImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileViewImplTest.kt
@@ -17,6 +17,7 @@
package com.android.systemui.qs.tileimpl
import android.content.Context
+import android.graphics.Rect
import android.graphics.drawable.Drawable
import android.service.quicksettings.Tile
import android.testing.AndroidTestingRunner
@@ -474,6 +475,67 @@
assertThat(tileView.isLongPressEffectInitialized).isFalse()
}
+ @Test
+ fun onPrepareForLaunch_paddingForLaunchAnimationIsConfigured() {
+ val startingWidth = 100
+ val startingHeight = 50
+ val deltaWidth = (QSTileViewImpl.LONG_PRESS_EFFECT_WIDTH_SCALE - 1f) * startingWidth
+ val deltaHeight = (QSTileViewImpl.LONG_PRESS_EFFECT_HEIGHT_SCALE - 1f) * startingHeight
+
+ // GIVEN that long-press effect properties are initialized
+ tileView.initializeLongPressProperties(startingHeight, startingWidth)
+
+ // WHEN the tile is preparing for the launch animation
+ tileView.prepareForLaunch()
+
+ // THE animation padding corresponds to the tile's growth due to the effect
+ val padding = tileView.getPaddingForLaunchAnimation()
+ assertThat(padding).isEqualTo(
+ Rect(
+ -deltaWidth.toInt() / 2,
+ -deltaHeight.toInt() / 2,
+ deltaWidth.toInt() / 2,
+ deltaHeight.toInt() / 2,
+ )
+ )
+ }
+
+ @Test
+ fun onActivityLaunchAnimationEnd_onFreshTile_longPressPropertiesAreReset() {
+ // WHEN an activity launch animation ends on a fresh tile
+ tileView.onActivityLaunchAnimationEnd()
+
+ // THEN the tile's long-press effect properties are reset by default
+ assertThat(tileView.haveLongPressPropertiesBeenReset).isTrue()
+ }
+
+ @Test
+ fun onUpdateLongPressEffectProperties_duringLongPressEffect_propertiesAreNotReset() {
+ // GIVEN a state that supports long-press
+ val state = QSTile.State()
+ tileView.changeState(state)
+
+ // WHEN the long-press effect is updating the properties
+ tileView.updateLongPressEffectProperties(1f)
+
+ // THEN the tile's long-press effect properties haven't reset
+ assertThat(tileView.haveLongPressPropertiesBeenReset).isFalse()
+ }
+
+ @Test
+ fun onActivityLaunchAnimationEnd_afterLongPressEffect_longPressPropertiesAreReset() {
+ // GIVEN a state that supports long-press and the long-press effect updating
+ val state = QSTile.State()
+ tileView.changeState(state)
+ tileView.updateLongPressEffectProperties(1f)
+
+ // WHEN an activity launch animation ends on a fresh tile
+ tileView.onActivityLaunchAnimationEnd()
+
+ // THEN the tile's long-press effect properties are reset
+ assertThat(tileView.haveLongPressPropertiesBeenReset).isTrue()
+ }
+
class FakeTileView(
context: Context,
collapsed: Boolean,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt
index 605dc14..2c49e92 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt
@@ -21,11 +21,10 @@
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import android.testing.TestableLooper.RunWithLooper
-import android.view.View
import androidx.test.filters.SmallTest
import com.android.internal.logging.MetricsLogger
-import com.android.systemui.res.R
import com.android.systemui.SysuiTestCase
+import com.android.systemui.animation.Expandable
import com.android.systemui.classifier.FalsingManagerFake
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.plugins.qs.QSTile
@@ -34,6 +33,7 @@
import com.android.systemui.qs.QsEventLogger
import com.android.systemui.qs.logging.QSLogger
import com.android.systemui.qs.tileimpl.QSTileImpl
+import com.android.systemui.res.R
import com.android.systemui.statusbar.policy.BatteryController
import com.android.systemui.util.settings.FakeSettings
import com.android.systemui.util.settings.SecureSettings
@@ -59,24 +59,15 @@
private const val USER = 10
}
- @Mock
- private lateinit var userContext: Context
- @Mock
- private lateinit var qsHost: QSHost
- @Mock
- private lateinit var uiEventLogger: QsEventLogger
- @Mock
- private lateinit var metricsLogger: MetricsLogger
- @Mock
- private lateinit var statusBarStateController: StatusBarStateController
- @Mock
- private lateinit var activityStarter: ActivityStarter
- @Mock
- private lateinit var qsLogger: QSLogger
- @Mock
- private lateinit var batteryController: BatteryController
- @Mock
- private lateinit var view: View
+ @Mock private lateinit var userContext: Context
+ @Mock private lateinit var qsHost: QSHost
+ @Mock private lateinit var uiEventLogger: QsEventLogger
+ @Mock private lateinit var metricsLogger: MetricsLogger
+ @Mock private lateinit var statusBarStateController: StatusBarStateController
+ @Mock private lateinit var activityStarter: ActivityStarter
+ @Mock private lateinit var qsLogger: QSLogger
+ @Mock private lateinit var batteryController: BatteryController
+ @Mock private lateinit var expandable: Expandable
private lateinit var secureSettings: SecureSettings
private lateinit var testableLooper: TestableLooper
private lateinit var tile: BatterySaverTile
@@ -91,7 +82,8 @@
secureSettings = FakeSettings()
- tile = BatterySaverTile(
+ tile =
+ BatterySaverTile(
qsHost,
uiEventLogger,
testableLooper.looper,
@@ -102,7 +94,8 @@
activityStarter,
qsLogger,
batteryController,
- secureSettings)
+ secureSettings
+ )
tile.initialize()
testableLooper.processAllMessages()
@@ -131,23 +124,23 @@
@Test
fun testClickingPowerSavePassesView() {
tile.onPowerSaveChanged(true)
- tile.handleClick(view)
+ tile.handleClick(expandable)
tile.onPowerSaveChanged(false)
- tile.handleClick(view)
+ tile.handleClick(expandable)
- verify(batteryController).setPowerSaveMode(true, view)
- verify(batteryController).setPowerSaveMode(false, view)
+ verify(batteryController).setPowerSaveMode(true, expandable)
+ verify(batteryController).setPowerSaveMode(false, expandable)
}
@Test
fun testStopListeningClearsViewInController() {
clearInvocations(batteryController)
tile.handleSetListening(true)
- verify(batteryController, never()).clearLastPowerSaverStartView()
+ verify(batteryController, never()).clearLastPowerSaverStartExpandable()
tile.handleSetListening(false)
- verify(batteryController).clearLastPowerSaverStartView()
+ verify(batteryController).clearLastPowerSaverStartExpandable()
}
@Test
@@ -158,7 +151,7 @@
tile.handleUpdateState(state, /* arg= */ null)
assertThat(state.icon)
- .isEqualTo(QSTileImpl.ResourceIcon.get(R.drawable.qs_battery_saver_icon_off))
+ .isEqualTo(QSTileImpl.ResourceIcon.get(R.drawable.qs_battery_saver_icon_off))
}
@Test
@@ -169,6 +162,6 @@
tile.handleUpdateState(state, /* arg= */ null)
assertThat(state.icon)
- .isEqualTo(QSTileImpl.ResourceIcon.get(R.drawable.qs_battery_saver_icon_on))
+ .isEqualTo(QSTileImpl.ResourceIcon.get(R.drawable.qs_battery_saver_icon_on))
}
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt
index cca1344..1173fa3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt
@@ -26,12 +26,12 @@
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import android.view.ContextThemeWrapper
-import android.view.View
import androidx.test.filters.SmallTest
import com.android.internal.logging.MetricsLogger
import com.android.systemui.res.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.DialogTransitionAnimator
+import com.android.systemui.animation.Expandable
import com.android.systemui.classifier.FalsingManagerFake
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.plugins.qs.QSTile
@@ -42,7 +42,6 @@
import com.android.systemui.qs.tileimpl.QSTileImpl
import com.android.systemui.statusbar.policy.ZenModeController
import com.android.systemui.util.mockito.any
-import com.android.systemui.util.mockito.eq
import com.android.systemui.util.mockito.nullable
import com.android.systemui.util.settings.FakeSettings
import com.android.systemui.util.settings.SecureSettings
@@ -99,6 +98,12 @@
@Mock
private lateinit var hostDialog: Dialog
+ @Mock
+ private lateinit var expandable: Expandable
+
+ @Mock
+ private lateinit var controller: DialogTransitionAnimator.Controller
+
private lateinit var secureSettings: SecureSettings
private lateinit var testableLooper: TestableLooper
private lateinit var tile: DndTile
@@ -119,6 +124,7 @@
}
}
whenever(qsHost.context).thenReturn(wrappedContext)
+ whenever(expandable.dialogTransitionController(any())).thenReturn(controller)
tile = DndTile(
qsHost,
@@ -187,11 +193,10 @@
secureSettings.putIntForUser(KEY, Settings.Secure.ZEN_DURATION_PROMPT, DEFAULT_USER)
testableLooper.processAllMessages()
- val view = View(context)
- tile.handleClick(view)
+ tile.handleClick(expandable)
testableLooper.processAllMessages()
- verify(mDialogTransitionAnimator).showFromView(any(), eq(view), nullable(), anyBoolean())
+ verify(mDialogTransitionAnimator).show(any(), any(), anyBoolean())
}
@Test
@@ -201,8 +206,7 @@
secureSettings.putIntForUser(KEY, 60, DEFAULT_USER)
testableLooper.processAllMessages()
- val view = View(context)
- tile.handleClick(view)
+ tile.handleClick(expandable)
testableLooper.processAllMessages()
verify(mDialogTransitionAnimator, never())
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FontScalingTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FontScalingTileTest.kt
index 1f5ebfe..1c42dd1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FontScalingTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FontScalingTileTest.kt
@@ -20,12 +20,12 @@
import android.provider.Settings
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
-import android.view.View
import androidx.test.filters.SmallTest
import com.android.internal.logging.MetricsLogger
import com.android.systemui.SysuiTestCase
import com.android.systemui.accessibility.fontscaling.FontScalingDialogDelegate
import com.android.systemui.animation.DialogTransitionAnimator
+import com.android.systemui.animation.Expandable
import com.android.systemui.classifier.FalsingManagerFake
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.plugins.statusbar.StatusBarStateController
@@ -37,7 +37,6 @@
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.eq
-import com.android.systemui.util.mockito.nullable
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
import org.junit.After
@@ -67,6 +66,8 @@
@Mock private lateinit var keyguardStateController: KeyguardStateController
@Mock private lateinit var fontScalingDialogDelegate: FontScalingDialogDelegate
@Mock private lateinit var dialog: SystemUIDialog
+ @Mock private lateinit var expandable: Expandable
+ @Mock private lateinit var controller: DialogTransitionAnimator.Controller
private lateinit var testableLooper: TestableLooper
private lateinit var systemClock: FakeSystemClock
@@ -81,6 +82,7 @@
testableLooper = TestableLooper.get(this)
`when`(qsHost.getContext()).thenReturn(mContext)
`when`(fontScalingDialogDelegate.createDialog()).thenReturn(dialog)
+ `when`(expandable.dialogTransitionController(any())).thenReturn(controller)
systemClock = FakeSystemClock()
backgroundDelayableExecutor = FakeExecutor(systemClock)
@@ -119,8 +121,7 @@
@Test
fun clickTile_screenUnlocked_showDialogAnimationFromView() {
`when`(keyguardStateController.isShowing).thenReturn(false)
- val view = View(context)
- fontScalingTile.click(view)
+ fontScalingTile.click(expandable)
testableLooper.processAllMessages()
verify(activityStarter)
@@ -132,14 +133,13 @@
eq(false)
)
argumentCaptor.value.run()
- verify(mDialogTransitionAnimator).showFromView(any(), eq(view), nullable(), anyBoolean())
+ verify(mDialogTransitionAnimator).show(any(), any(), anyBoolean())
}
@Test
fun clickTile_onLockScreen_neverShowDialogAnimationFromView() {
`when`(keyguardStateController.isShowing).thenReturn(true)
- val view = View(context)
- fontScalingTile.click(view)
+ fontScalingTile.click(expandable)
testableLooper.processAllMessages()
verify(activityStarter)
@@ -151,8 +151,7 @@
eq(false)
)
argumentCaptor.value.run()
- verify(mDialogTransitionAnimator, never())
- .showFromView(any(), eq(view), nullable(), anyBoolean())
+ verify(mDialogTransitionAnimator, never()).show(any(), any(), anyBoolean())
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/HearingDevicesTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/HearingDevicesTileTest.java
index 73aa54c..56671bf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/HearingDevicesTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/HearingDevicesTileTest.java
@@ -38,6 +38,7 @@
import com.android.systemui.Flags;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.accessibility.hearingaid.HearingDevicesDialogManager;
+import com.android.systemui.animation.Expandable;
import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -135,10 +136,10 @@
@Test
public void handleClick_dialogShown() {
- View view = new View(mContext);
- mTile.handleClick(view);
+ Expandable expandable = Expandable.fromView(new View(mContext));
+ mTile.handleClick(expandable);
mTestableLooper.processAllMessages();
- verify(mHearingDevicesDialogManager).showDialog(view);
+ verify(mHearingDevicesDialogManager).showDialog(expandable);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt b/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt
index 387f27d..effae5f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt
@@ -241,6 +241,7 @@
statusBarWinController,
sysUiState,
mock(),
+ mock(),
userTracker,
wakefulnessLifecycle,
uiEventLogger,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ActionExecutorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ActionExecutorTest.kt
index 91f3912..5e7d8fb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ActionExecutorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ActionExecutorTest.kt
@@ -28,7 +28,6 @@
import com.android.systemui.util.mockito.argumentCaptor
import com.android.systemui.util.mockito.mock
import com.google.common.truth.Truth.assertThat
-import kotlin.test.Ignore
import kotlin.test.Test
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestCoroutineScheduler
@@ -56,7 +55,6 @@
private lateinit var actionExecutor: ActionExecutor
- @Ignore // Fixed with newer mockito version (in main)
@Test
fun startSharedTransition_callsLaunchIntent() = runTest {
actionExecutor = createActionExecutor()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/TakeScreenshotExecutorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/TakeScreenshotExecutorTest.kt
index 0f37143..bf7d909 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/TakeScreenshotExecutorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/TakeScreenshotExecutorTest.kt
@@ -69,8 +69,9 @@
@Before
fun setUp() {
- whenever(controllerFactory.create(eq(0), any())).thenReturn(controller0)
- whenever(controllerFactory.create(eq(1), any())).thenReturn(controller1)
+ whenever(controllerFactory.create(any(), any())).thenAnswer {
+ if (it.getArgument<Display>(0).displayId == 0) controller0 else controller1
+ }
whenever(notificationControllerFactory.create(eq(0))).thenReturn(notificationsController0)
whenever(notificationControllerFactory.create(eq(1))).thenReturn(notificationsController1)
}
@@ -78,12 +79,14 @@
@Test
fun executeScreenshots_severalDisplays_callsControllerForEachOne() =
testScope.runTest {
- setDisplays(display(TYPE_INTERNAL, id = 0), display(TYPE_EXTERNAL, id = 1))
+ val internalDisplay = display(TYPE_INTERNAL, id = 0)
+ val externalDisplay = display(TYPE_EXTERNAL, id = 1)
+ setDisplays(internalDisplay, externalDisplay)
val onSaved = { _: Uri? -> }
screenshotExecutor.executeScreenshots(createScreenshotRequest(), onSaved, callback)
- verify(controllerFactory).create(eq(0), any())
- verify(controllerFactory).create(eq(1), any())
+ verify(controllerFactory).create(eq(internalDisplay), any())
+ verify(controllerFactory).create(eq(externalDisplay), any())
val capturer = ArgumentCaptor<ScreenshotData>()
@@ -107,7 +110,9 @@
@Test
fun executeScreenshots_providedImageType_callsOnlyDefaultDisplayController() =
testScope.runTest {
- setDisplays(display(TYPE_INTERNAL, id = 0), display(TYPE_EXTERNAL, id = 1))
+ val internalDisplay = display(TYPE_INTERNAL, id = 0)
+ val externalDisplay = display(TYPE_EXTERNAL, id = 1)
+ setDisplays(internalDisplay, externalDisplay)
val onSaved = { _: Uri? -> }
screenshotExecutor.executeScreenshots(
createScreenshotRequest(TAKE_SCREENSHOT_PROVIDED_IMAGE),
@@ -115,8 +120,8 @@
callback
)
- verify(controllerFactory).create(eq(0), any())
- verify(controllerFactory, never()).create(eq(1), any())
+ verify(controllerFactory).create(eq(internalDisplay), any())
+ verify(controllerFactory, never()).create(eq(externalDisplay), any())
val capturer = ArgumentCaptor<ScreenshotData>()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ui/viewmodel/ScreenshotViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ui/viewmodel/ScreenshotViewModelTest.kt
index d44e26c..e32086b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ui/viewmodel/ScreenshotViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ui/viewmodel/ScreenshotViewModelTest.kt
@@ -34,20 +34,21 @@
assertThat(viewModel.actions.value).isEmpty()
- viewModel.addAction(appearance, onclick)
+ viewModel.addAction(appearance, true, onclick)
assertThat(viewModel.actions.value).hasSize(1)
val added = viewModel.actions.value[0]
assertThat(added.appearance).isEqualTo(appearance)
assertThat(added.onClicked).isEqualTo(onclick)
+ assertThat(added.showDuringEntrance).isTrue()
}
@Test
fun testRemoveAction() {
val viewModel = ScreenshotViewModel(accessibilityManager)
- val firstId = viewModel.addAction(ActionButtonAppearance(null, "", ""), {})
- val secondId = viewModel.addAction(appearance, onclick)
+ val firstId = viewModel.addAction(ActionButtonAppearance(null, "", ""), false, {})
+ val secondId = viewModel.addAction(appearance, false, onclick)
assertThat(viewModel.actions.value).hasSize(2)
assertThat(firstId).isNotEqualTo(secondId)
@@ -58,13 +59,14 @@
val remaining = viewModel.actions.value[0]
assertThat(remaining.appearance).isEqualTo(appearance)
+ assertThat(remaining.showDuringEntrance).isFalse()
assertThat(remaining.onClicked).isEqualTo(onclick)
}
@Test
fun testUpdateActionAppearance() {
val viewModel = ScreenshotViewModel(accessibilityManager)
- val id = viewModel.addAction(appearance, onclick)
+ val id = viewModel.addAction(appearance, false, onclick)
val otherAppearance = ActionButtonAppearance(null, "Other", "Other")
viewModel.updateActionAppearance(id, otherAppearance)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt
index 19b137c..537049c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt
@@ -18,7 +18,7 @@
import android.graphics.Rect
import android.os.PowerManager
-import android.platform.test.flag.junit.FlagsParameterization
+import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import android.testing.ViewUtils
import android.view.MotionEvent
@@ -27,12 +27,14 @@
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.test.filters.SmallTest
+import com.android.compose.animation.scene.ObservableTransitionState
import com.android.compose.animation.scene.SceneKey
import com.android.systemui.Flags
import com.android.systemui.SysuiTestCase
import com.android.systemui.ambient.touch.TouchHandler
import com.android.systemui.ambient.touch.TouchMonitor
import com.android.systemui.ambient.touch.dagger.AmbientTouchComponent
+import com.android.systemui.bouncer.data.repository.fakeKeyguardBouncerRepository
import com.android.systemui.communal.data.repository.FakeCommunalRepository
import com.android.systemui.communal.data.repository.fakeCommunalRepository
import com.android.systemui.communal.domain.interactor.communalInteractor
@@ -41,18 +43,11 @@
import com.android.systemui.communal.ui.viewmodel.CommunalViewModel
import com.android.systemui.communal.util.CommunalColors
import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.flags.andSceneContainer
-import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
-import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
-import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.testDispatcher
import com.android.systemui.kosmos.testScope
import com.android.systemui.res.R
-import com.android.systemui.scene.domain.interactor.sceneInteractor
-import com.android.systemui.scene.shared.flag.SceneContainerFlag
-import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.shared.model.sceneDataSourceDelegator
import com.android.systemui.shade.domain.interactor.shadeInteractor
import com.android.systemui.statusbar.phone.SystemUIDialogFactory
@@ -60,6 +55,7 @@
import com.android.systemui.util.mockito.any
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
@@ -72,14 +68,12 @@
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
-import platform.test.runner.parameterized.ParameterizedAndroidJunit4
-import platform.test.runner.parameterized.Parameters
@ExperimentalCoroutinesApi
-@RunWith(ParameterizedAndroidJunit4::class)
+@RunWith(AndroidTestingRunner::class)
@TestableLooper.RunWithLooper(setAsMainLooper = true)
@SmallTest
-class GlanceableHubContainerControllerTest(flags: FlagsParameterization?) : SysuiTestCase() {
+class GlanceableHubContainerControllerTest : SysuiTestCase() {
private val kosmos: Kosmos =
testKosmos().apply {
// UnconfinedTestDispatcher makes testing simpler due to CommunalInteractor flows using
@@ -101,10 +95,6 @@
private lateinit var communalRepository: FakeCommunalRepository
private lateinit var underTest: GlanceableHubContainerController
- init {
- mSetFlagsRule.setFlagsParameterization(flags!!)
- }
-
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
@@ -128,7 +118,6 @@
communalInteractor,
communalViewModel,
dialogFactory,
- keyguardTransitionInteractor,
keyguardInteractor,
shadeInteractor,
powerManager,
@@ -171,7 +160,6 @@
communalInteractor,
communalViewModel,
dialogFactory,
- keyguardTransitionInteractor,
keyguardInteractor,
shadeInteractor,
powerManager,
@@ -217,13 +205,39 @@
}
@Test
+ fun onTouchEvent_communalTransitioning_interceptsTouches() =
+ with(kosmos) {
+ testScope.runTest {
+ // Communal is opening.
+ communalRepository.setTransitionState(
+ flowOf(
+ ObservableTransitionState.Transition(
+ fromScene = CommunalScenes.Blank,
+ toScene = CommunalScenes.Communal,
+ currentScene = flowOf(CommunalScenes.Blank),
+ progress = flowOf(0.5f),
+ isInitiatedByUserInput = true,
+ isUserInputOngoing = flowOf(true)
+ )
+ )
+ )
+ testableLooper.processAllMessages()
+
+ // Touch events are intercepted.
+ assertThat(underTest.onTouchEvent(DOWN_EVENT)).isTrue()
+ // User activity sent to PowerManager.
+ verify(powerManager).userActivity(any(), any(), any())
+ }
+ }
+
+ @Test
fun onTouchEvent_communalOpen_interceptsTouches() =
with(kosmos) {
testScope.runTest {
// Communal is open.
goToScene(CommunalScenes.Communal)
- // Touch events are intercepted outside of any gesture areas.
+ // Touch events are intercepted.
assertThat(underTest.onTouchEvent(DOWN_EVENT)).isTrue()
// User activity sent to PowerManager.
verify(powerManager).userActivity(any(), any(), any())
@@ -238,11 +252,7 @@
goToScene(CommunalScenes.Communal)
// Bouncer is visible.
- fakeKeyguardTransitionRepository.sendTransitionSteps(
- KeyguardState.GLANCEABLE_HUB,
- KeyguardState.PRIMARY_BOUNCER,
- testScope
- )
+ fakeKeyguardBouncerRepository.setPrimaryShow(true)
testableLooper.processAllMessages()
// Touch events are not intercepted.
@@ -294,7 +304,6 @@
communalInteractor,
communalViewModel,
dialogFactory,
- keyguardTransitionInteractor,
keyguardInteractor,
shadeInteractor,
powerManager,
@@ -314,7 +323,6 @@
communalInteractor,
communalViewModel,
dialogFactory,
- keyguardTransitionInteractor,
keyguardInteractor,
shadeInteractor,
powerManager,
@@ -368,11 +376,7 @@
goToScene(CommunalScenes.Communal)
// Bouncer is visible.
- fakeKeyguardTransitionRepository.sendTransitionSteps(
- KeyguardState.GLANCEABLE_HUB,
- KeyguardState.PRIMARY_BOUNCER,
- testScope
- )
+ fakeKeyguardBouncerRepository.setPrimaryShow(true)
testableLooper.processAllMessages()
assertThat(underTest.lifecycle.currentState).isEqualTo(Lifecycle.State.STARTED)
@@ -387,11 +391,7 @@
goToScene(CommunalScenes.Communal)
// Bouncer is visible.
- fakeKeyguardTransitionRepository.sendTransitionSteps(
- KeyguardState.GLANCEABLE_HUB,
- KeyguardState.ALTERNATE_BOUNCER,
- testScope
- )
+ fakeKeyguardBouncerRepository.setAlternateVisible(true)
testableLooper.processAllMessages()
assertThat(underTest.lifecycle.currentState).isEqualTo(Lifecycle.State.STARTED)
@@ -452,6 +452,53 @@
}
}
+ @Test
+ fun gestureExclusionZone_unsetWhenShadeOpen() =
+ with(kosmos) {
+ testScope.runTest {
+ goToScene(CommunalScenes.Communal)
+
+ // Shade shows up.
+ shadeTestUtil.setQsExpansion(1.0f)
+ testableLooper.processAllMessages()
+
+ // Exclusion rects are unset.
+ assertThat(containerView.systemGestureExclusionRects).isEmpty()
+ }
+ }
+
+ @Test
+ fun gestureExclusionZone_unsetWhenBouncerOpen() =
+ with(kosmos) {
+ testScope.runTest {
+ goToScene(CommunalScenes.Communal)
+
+ // Bouncer is visible.
+ fakeKeyguardBouncerRepository.setPrimaryShow(true)
+ testableLooper.processAllMessages()
+
+ // Exclusion rects are unset.
+ assertThat(containerView.systemGestureExclusionRects).isEmpty()
+ }
+ }
+
+ @Test
+ fun gestureExclusionZone_unsetWhenHubClosed() =
+ with(kosmos) {
+ testScope.runTest {
+ goToScene(CommunalScenes.Communal)
+
+ // Exclusion rect is set.
+ assertThat(containerView.systemGestureExclusionRects).hasSize(1)
+
+ // Leave the hub.
+ goToScene(CommunalScenes.Blank)
+
+ // Exclusion rect is unset.
+ assertThat(containerView.systemGestureExclusionRects).isEmpty()
+ }
+ }
+
private fun initAndAttachContainerView() {
containerView = View(context)
@@ -467,13 +514,6 @@
}
private fun goToScene(scene: SceneKey) {
- if (SceneContainerFlag.isEnabled) {
- if (scene == CommunalScenes.Communal) {
- kosmos.sceneInteractor.changeScene(Scenes.Communal, "test")
- } else {
- kosmos.sceneInteractor.changeScene(Scenes.Lockscreen, "test")
- }
- }
communalRepository.changeScene(scene)
testableLooper.processAllMessages()
}
@@ -502,11 +542,5 @@
MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, CONTAINER_WIDTH.toFloat(), 0f, 0)
private val MOVE_EVENT = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_MOVE, 0f, 0f, 0)
private val UP_EVENT = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_UP, 0f, 0f, 0)
-
- @JvmStatic
- @Parameters(name = "{0}")
- fun getParams(): List<FlagsParameterization> {
- return FlagsParameterization.allCombinationsOf().andSceneContainer()
- }
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
index 81e20c1..e1cdda4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
@@ -18,6 +18,7 @@
import static com.android.keyguard.KeyguardClockSwitch.LARGE;
import static com.android.keyguard.KeyguardClockSwitch.SMALL;
+import static com.android.systemui.Flags.FLAG_SHADE_COLLAPSE_ACTIVITY_LAUNCH_FIX;
import static com.android.systemui.shade.ShadeExpansionStateManagerKt.STATE_CLOSED;
import static com.android.systemui.shade.ShadeExpansionStateManagerKt.STATE_OPEN;
import static com.android.systemui.shade.ShadeExpansionStateManagerKt.STATE_OPENING;
@@ -47,6 +48,7 @@
import android.graphics.Point;
import android.os.PowerManager;
import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.view.MotionEvent;
@@ -426,6 +428,7 @@
public void testOnTouchEvent_expansionResumesAfterBriefTouch() {
mFalsingManager.setIsClassifierEnabled(true);
mFalsingManager.setIsFalseTouch(false);
+ mNotificationPanelViewController.setForceFlingAnimationForTest(true);
// Start shade collapse with swipe up
onTouchEvent(MotionEvent.obtain(0L /* downTime */,
0L /* eventTime */, MotionEvent.ACTION_DOWN, 0f /* x */, 0f /* y */,
@@ -454,6 +457,7 @@
// fling should still be called after a touch that does not exceed touch slop
assertThat(mNotificationPanelViewController.isClosing()).isTrue();
assertThat(mNotificationPanelViewController.isFlinging()).isTrue();
+ mNotificationPanelViewController.setForceFlingAnimationForTest(false);
}
@Test
@@ -675,6 +679,32 @@
}
@Test
+ @EnableFlags(FLAG_SHADE_COLLAPSE_ACTIVITY_LAUNCH_FIX)
+ public void testCanBeCollapsed_expandedInKeyguard() {
+ mStatusBarStateController.setState(KEYGUARD);
+ mNotificationPanelViewController.setExpandedFraction(1f);
+
+ assertThat(mNotificationPanelViewController.canBeCollapsed()).isFalse();
+ }
+
+ @Test
+ @EnableFlags(FLAG_SHADE_COLLAPSE_ACTIVITY_LAUNCH_FIX)
+ public void testCanBeCollapsed_expandedInShade() {
+ mStatusBarStateController.setState(SHADE);
+ mNotificationPanelViewController.setExpandedFraction(1f);
+ assertThat(mNotificationPanelViewController.canBeCollapsed()).isTrue();
+ }
+
+ @Test
+ @DisableFlags(FLAG_SHADE_COLLAPSE_ACTIVITY_LAUNCH_FIX)
+ public void testCanBeCollapsed_expandedInKeyguard_flagDisabled() {
+ mStatusBarStateController.setState(KEYGUARD);
+ mNotificationPanelViewController.setExpandedFraction(1f);
+
+ assertThat(mNotificationPanelViewController.canBeCollapsed()).isTrue();
+ }
+
+ @Test
public void testSwipeWhileLocked_notifiesKeyguardState() {
mStatusBarStateController.setState(KEYGUARD);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
index 112829a..a867b0f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
@@ -17,12 +17,15 @@
package com.android.systemui.shade
import android.content.Context
+import android.platform.test.annotations.RequiresFlagsDisabled
import android.platform.test.flag.junit.FlagsParameterization
+import android.testing.TestableLooper
import android.testing.TestableLooper.RunWithLooper
import android.view.KeyEvent
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
+import android.view.ViewTreeObserver
import androidx.test.filters.SmallTest
import com.android.keyguard.KeyguardSecurityContainerController
import com.android.keyguard.LegacyLockIconViewController
@@ -72,7 +75,6 @@
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
-import java.util.Optional
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.emptyFlow
@@ -80,12 +82,12 @@
import kotlinx.coroutines.test.runTest
import org.junit.Assert.assertEquals
import org.junit.Before
-import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
import org.mockito.Mock
import org.mockito.Mockito.anyFloat
+import org.mockito.Mockito.atLeast
import org.mockito.Mockito.mock
import org.mockito.Mockito.never
import org.mockito.Mockito.times
@@ -93,6 +95,7 @@
import org.mockito.MockitoAnnotations
import platform.test.runner.parameterized.ParameterizedAndroidJunit4
import platform.test.runner.parameterized.Parameters
+import java.util.Optional
import org.mockito.Mockito.`when` as whenever
@OptIn(ExperimentalCoroutinesApi::class)
@@ -152,6 +155,7 @@
private lateinit var underTest: NotificationShadeWindowViewController
private lateinit var testScope: TestScope
+ private lateinit var testableLooper: TestableLooper
private lateinit var featureFlagsClassic: FakeFeatureFlagsClassic
@@ -181,6 +185,7 @@
mSetFlagsRule.enableFlags(Flags.FLAG_REVAMPED_BOUNCER_MESSAGES)
testScope = TestScope()
+ testableLooper = TestableLooper.get(this)
falsingCollector = FalsingCollectorFake()
fakeClock = FakeSystemClock()
underTest =
@@ -407,6 +412,7 @@
}
@Test
+ @DisableSceneContainer
fun handleDispatchTouchEvent_glanceableHubIntercepts_returnsTrue() {
whenever(mGlanceableHubContainerController.onTouchEvent(DOWN_EVENT)).thenReturn(true)
underTest.setStatusBarViewController(phoneStatusBarViewController)
@@ -559,29 +565,42 @@
}
@Test
- @Ignore("b/321332798")
+ @DisableSceneContainer
fun setsUpCommunalHubLayout_whenFlagEnabled() {
whenever(mGlanceableHubContainerController.communalAvailable())
- .thenReturn(MutableStateFlow(true))
+ .thenReturn(MutableStateFlow(true))
- val mockCommunalView = mock(View::class.java)
+ val communalView = View(context)
whenever(mGlanceableHubContainerController.initView(any<Context>()))
- .thenReturn(mockCommunalView)
+ .thenReturn(communalView)
val mockCommunalPlaceholder = mock(View::class.java)
val fakeViewIndex = 20
whenever(view.findViewById<View>(R.id.communal_ui_stub)).thenReturn(mockCommunalPlaceholder)
whenever(view.indexOfChild(mockCommunalPlaceholder)).thenReturn(fakeViewIndex)
whenever(view.context).thenReturn(context)
+ whenever(view.viewTreeObserver).thenReturn(mock(ViewTreeObserver::class.java))
underTest.setupCommunalHubLayout()
- // Communal view added as a child of the container at the proper index, the stub is removed.
- verify(view).removeView(mockCommunalPlaceholder)
- verify(view).addView(eq(mockCommunalView), eq(fakeViewIndex))
+ // Simluate attaching the view so flow collection starts.
+ val onAttachStateChangeListenerArgumentCaptor = ArgumentCaptor.forClass(
+ View.OnAttachStateChangeListener::class.java
+ )
+ verify(view, atLeast(1)).addOnAttachStateChangeListener(
+ onAttachStateChangeListenerArgumentCaptor.capture()
+ )
+ for (listener in onAttachStateChangeListenerArgumentCaptor.allValues) {
+ listener.onViewAttachedToWindow(view)
+ }
+ testableLooper.processAllMessages()
+
+ // Communal view added as a child of the container at the proper index.
+ verify(view).addView(eq(communalView), eq(fakeViewIndex))
}
@Test
+ @RequiresFlagsDisabled(Flags.FLAG_COMMUNAL_HUB)
fun doesNotSetupCommunalHubLayout_whenFlagDisabled() {
whenever(mGlanceableHubContainerController.communalAvailable())
.thenReturn(MutableStateFlow(false))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerImplBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerImplBaseTest.java
index 317e35c..04fa590 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerImplBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerImplBaseTest.java
@@ -216,6 +216,7 @@
keyguardTransitionInteractor,
() -> sceneInteractor,
() -> mKosmos.getFromGoneTransitionInteractor(),
+ () -> mKosmos.getFromLockscreenTransitionInteractor(),
() -> mKosmos.getSharedNotificationContainerInteractor(),
mTestScope);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyboardShortcutsReceiverTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyboardShortcutsReceiverTest.java
index bedb2b3..e0eb99c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyboardShortcutsReceiverTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyboardShortcutsReceiverTest.java
@@ -16,120 +16,161 @@
package com.android.systemui.statusbar;
+import static com.android.systemui.Flags.FLAG_KEYBOARD_SHORTCUT_HELPER_REWRITE;
+
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import android.content.Intent;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
import com.android.dx.mockito.inline.extended.ExtendedMockito;
+import com.android.dx.mockito.inline.extended.StaticMockitoSession;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.flags.FakeFeatureFlags;
import com.android.systemui.flags.Flags;
import com.android.systemui.shared.recents.utilities.Utilities;
+import org.junit.After;
import org.junit.Before;
-import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
-import org.mockito.MockitoSession;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoRule;
+import org.mockito.MockitoAnnotations;
import org.mockito.quality.Strictness;
@SmallTest
@RunWith(AndroidJUnit4.class)
public class KeyboardShortcutsReceiverTest extends SysuiTestCase {
- @Rule public MockitoRule mockito = MockitoJUnit.rule();
+ private static final Intent SHOW_INTENT = new Intent(Intent.ACTION_SHOW_KEYBOARD_SHORTCUTS);
+ private static final Intent DISMISS_INTENT =
+ new Intent(Intent.ACTION_DISMISS_KEYBOARD_SHORTCUTS);
+ private StaticMockitoSession mockitoSession;
private KeyboardShortcutsReceiver mKeyboardShortcutsReceiver;
- private Intent mIntent;
- private FakeFeatureFlags mFeatureFlags = new FakeFeatureFlags();
+ private final FakeFeatureFlags mFeatureFlags = new FakeFeatureFlags();
@Mock private KeyboardShortcuts mKeyboardShortcuts;
@Mock private KeyboardShortcutListSearch mKeyboardShortcutListSearch;
@Before
public void setUp() {
- mIntent = new Intent(Intent.ACTION_SHOW_KEYBOARD_SHORTCUTS);
+ MockitoAnnotations.initMocks(this);
+ mSetFlagsRule.disableFlags(FLAG_KEYBOARD_SHORTCUT_HELPER_REWRITE);
mKeyboardShortcuts.mContext = mContext;
mKeyboardShortcutListSearch.mContext = mContext;
KeyboardShortcuts.sInstance = mKeyboardShortcuts;
KeyboardShortcutListSearch.sInstance = mKeyboardShortcutListSearch;
+
+ mKeyboardShortcutsReceiver = spy(new KeyboardShortcutsReceiver(mFeatureFlags));
+ }
+
+ @Before
+ public void startStaticMocking() {
+ mockitoSession =
+ ExtendedMockito.mockitoSession()
+ .spyStatic(Utilities.class)
+ .strictness(Strictness.LENIENT)
+ .startMocking();
+ }
+
+ @After
+ public void endStaticMocking() {
+ mockitoSession.finishMocking();
}
@Test
public void onReceive_whenFlagOffDeviceIsTablet_showKeyboardShortcuts() {
- MockitoSession mockitoSession = ExtendedMockito.mockitoSession()
- .spyStatic(Utilities.class)
- .strictness(Strictness.LENIENT)
- .startMocking();
mFeatureFlags.set(Flags.SHORTCUT_LIST_SEARCH_LAYOUT, false);
- mKeyboardShortcutsReceiver = spy(new KeyboardShortcutsReceiver(mFeatureFlags));
when(Utilities.isLargeScreen(mContext)).thenReturn(true);
- mKeyboardShortcutsReceiver.onReceive(mContext, mIntent);
+ mKeyboardShortcutsReceiver.onReceive(mContext, SHOW_INTENT);
verify(mKeyboardShortcuts).showKeyboardShortcuts(anyInt());
verify(mKeyboardShortcutListSearch, never()).showKeyboardShortcuts(anyInt());
- mockitoSession.finishMocking();
}
@Test
public void onReceive_whenFlagOffDeviceIsNotTablet_showKeyboardShortcuts() {
- MockitoSession mockitoSession = ExtendedMockito.mockitoSession()
- .spyStatic(Utilities.class)
- .strictness(Strictness.LENIENT)
- .startMocking();
mFeatureFlags.set(Flags.SHORTCUT_LIST_SEARCH_LAYOUT, false);
- mKeyboardShortcutsReceiver = spy(new KeyboardShortcutsReceiver(mFeatureFlags));
when(Utilities.isLargeScreen(mContext)).thenReturn(false);
- mKeyboardShortcutsReceiver.onReceive(mContext, mIntent);
+ mKeyboardShortcutsReceiver.onReceive(mContext, SHOW_INTENT);
verify(mKeyboardShortcuts).showKeyboardShortcuts(anyInt());
verify(mKeyboardShortcutListSearch, never()).showKeyboardShortcuts(anyInt());
- mockitoSession.finishMocking();
}
@Test
public void onReceive_whenFlagOnDeviceIsTablet_showKeyboardShortcutListSearch() {
- MockitoSession mockitoSession = ExtendedMockito.mockitoSession()
- .spyStatic(Utilities.class)
- .strictness(Strictness.LENIENT)
- .startMocking();
mFeatureFlags.set(Flags.SHORTCUT_LIST_SEARCH_LAYOUT, true);
- mKeyboardShortcutsReceiver = spy(new KeyboardShortcutsReceiver(mFeatureFlags));
when(Utilities.isLargeScreen(mContext)).thenReturn(true);
- mKeyboardShortcutsReceiver.onReceive(mContext, mIntent);
+ mKeyboardShortcutsReceiver.onReceive(mContext, SHOW_INTENT);
verify(mKeyboardShortcuts, never()).showKeyboardShortcuts(anyInt());
verify(mKeyboardShortcutListSearch).showKeyboardShortcuts(anyInt());
- mockitoSession.finishMocking();
}
@Test
public void onReceive_whenFlagOnDeviceIsNotTablet_showKeyboardShortcuts() {
- MockitoSession mockitoSession = ExtendedMockito.mockitoSession()
- .spyStatic(Utilities.class)
- .strictness(Strictness.LENIENT)
- .startMocking();
mFeatureFlags.set(Flags.SHORTCUT_LIST_SEARCH_LAYOUT, true);
- mKeyboardShortcutsReceiver = spy(new KeyboardShortcutsReceiver(mFeatureFlags));
when(Utilities.isLargeScreen(mContext)).thenReturn(false);
- mKeyboardShortcutsReceiver.onReceive(mContext, mIntent);
+ mKeyboardShortcutsReceiver.onReceive(mContext, SHOW_INTENT);
verify(mKeyboardShortcuts).showKeyboardShortcuts(anyInt());
verify(mKeyboardShortcutListSearch, never()).showKeyboardShortcuts(anyInt());
- mockitoSession.finishMocking();
+ }
+
+ @Test
+ public void onShowIntent_rewriteFlagOn_oldFlagOn_isLargeScreen_doesNotLaunchOldVersions() {
+ mFeatureFlags.set(Flags.SHORTCUT_LIST_SEARCH_LAYOUT, true);
+ mSetFlagsRule.enableFlags(FLAG_KEYBOARD_SHORTCUT_HELPER_REWRITE);
+ when(Utilities.isLargeScreen(mContext)).thenReturn(true);
+
+ mKeyboardShortcutsReceiver.onReceive(mContext, SHOW_INTENT);
+
+ verifyZeroInteractions(mKeyboardShortcuts, mKeyboardShortcutListSearch);
+ }
+
+ @Test
+ public void onShowIntent_rewriteFlagOn_oldFlagOn_isSmallScreen_doesNotLaunchOldVersions() {
+ mFeatureFlags.set(Flags.SHORTCUT_LIST_SEARCH_LAYOUT, true);
+ mSetFlagsRule.enableFlags(FLAG_KEYBOARD_SHORTCUT_HELPER_REWRITE);
+ when(Utilities.isLargeScreen(mContext)).thenReturn(false);
+
+ mKeyboardShortcutsReceiver.onReceive(mContext, SHOW_INTENT);
+
+ verifyZeroInteractions(mKeyboardShortcuts, mKeyboardShortcutListSearch);
+ }
+
+ @Test
+ public void onDismissIntent_rewriteFlagOn_oldFlagOn_isLargeScreen_doesNotDismissOldVersions() {
+ mFeatureFlags.set(Flags.SHORTCUT_LIST_SEARCH_LAYOUT, true);
+ mSetFlagsRule.enableFlags(FLAG_KEYBOARD_SHORTCUT_HELPER_REWRITE);
+ when(Utilities.isLargeScreen(mContext)).thenReturn(true);
+
+ mKeyboardShortcutsReceiver.onReceive(mContext, DISMISS_INTENT);
+
+ verifyZeroInteractions(mKeyboardShortcuts, mKeyboardShortcutListSearch);
+ }
+
+ @Test
+ public void onDismissIntent_rewriteFlagOn_oldFlagOn_isSmallScreen_doesNotDismissOldVersions() {
+ mFeatureFlags.set(Flags.SHORTCUT_LIST_SEARCH_LAYOUT, true);
+ mSetFlagsRule.enableFlags(FLAG_KEYBOARD_SHORTCUT_HELPER_REWRITE);
+ when(Utilities.isLargeScreen(mContext)).thenReturn(false);
+
+ mKeyboardShortcutsReceiver.onReceive(mContext, DISMISS_INTENT);
+
+ verifyZeroInteractions(mKeyboardShortcuts, mKeyboardShortcutListSearch);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/footer/ui/viewmodel/FooterViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/footer/ui/viewmodel/FooterViewModelTest.kt
index 158f38d..347620a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/footer/ui/viewmodel/FooterViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/footer/ui/viewmodel/FooterViewModelTest.kt
@@ -19,12 +19,13 @@
package com.android.systemui.statusbar.notification.footer.ui.viewmodel
import android.platform.test.annotations.EnableFlags
+import android.platform.test.flag.junit.FlagsParameterization
import android.provider.Settings
-import android.testing.AndroidTestingRunner
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.flags.Flags
+import com.android.systemui.flags.andSceneContainer
import com.android.systemui.flags.fakeFeatureFlagsClassic
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
import com.android.systemui.keyguard.shared.model.StatusBarState
@@ -33,7 +34,7 @@
import com.android.systemui.power.shared.model.WakeSleepReason
import com.android.systemui.power.shared.model.WakefulnessState
import com.android.systemui.res.R
-import com.android.systemui.shade.data.repository.shadeRepository
+import com.android.systemui.shade.shadeTestUtil
import com.android.systemui.shared.settings.data.repository.fakeSecureSettingsRepository
import com.android.systemui.statusbar.notification.collection.render.NotifStats
import com.android.systemui.statusbar.notification.data.repository.activeNotificationListRepository
@@ -45,13 +46,16 @@
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
+import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4
+import platform.test.runner.parameterized.Parameters
-@RunWith(AndroidTestingRunner::class)
+@RunWith(ParameterizedAndroidJunit4::class)
@SmallTest
@EnableFlags(FooterViewRefactor.FLAG_NAME)
-class FooterViewModelTest : SysuiTestCase() {
+class FooterViewModelTest(flags: FlagsParameterization?) : SysuiTestCase() {
private val kosmos =
testKosmos().apply {
fakeFeatureFlagsClassic.apply { set(Flags.FULL_SCREEN_USER_SWITCHER, false) }
@@ -59,11 +63,29 @@
private val testScope = kosmos.testScope
private val activeNotificationListRepository = kosmos.activeNotificationListRepository
private val fakeKeyguardRepository = kosmos.fakeKeyguardRepository
- private val shadeRepository = kosmos.shadeRepository
private val powerRepository = kosmos.powerRepository
private val fakeSecureSettingsRepository = kosmos.fakeSecureSettingsRepository
- val underTest = kosmos.footerViewModel
+ private val shadeTestUtil by lazy { kosmos.shadeTestUtil }
+
+ private lateinit var underTest: FooterViewModel
+
+ companion object {
+ @JvmStatic
+ @Parameters(name = "{0}")
+ fun getParams(): List<FlagsParameterization> {
+ return FlagsParameterization.allCombinationsOf().andSceneContainer()
+ }
+ }
+
+ init {
+ mSetFlagsRule.setFlagsParameterization(flags!!)
+ }
+
+ @Before
+ fun setup() {
+ underTest = kosmos.footerViewModel
+ }
@Test
fun messageVisible_whenFilteredNotifications() =
@@ -146,11 +168,9 @@
val visible by collectLastValue(underTest.clearAllButton.isVisible)
runCurrent()
- // WHEN shade is expanded
+ // WHEN shade is expanded AND QS not expanded
fakeKeyguardRepository.setStatusBarState(StatusBarState.SHADE)
- shadeRepository.setLegacyShadeExpansion(1f)
- // AND QS not expanded
- shadeRepository.setQsExpansion(0f)
+ shadeTestUtil.setShadeAndQsExpansion(1f, 0f)
// AND device is awake
powerRepository.updateWakefulness(
rawState = WakefulnessState.AWAKE,
@@ -182,9 +202,9 @@
// WHEN shade is collapsed
fakeKeyguardRepository.setStatusBarState(StatusBarState.SHADE)
- shadeRepository.setLegacyShadeExpansion(0f)
+ shadeTestUtil.setShadeExpansion(0f)
// AND QS not expanded
- shadeRepository.setQsExpansion(0f)
+ shadeTestUtil.setQsExpansion(0f)
// AND device is awake
powerRepository.updateWakefulness(
rawState = WakefulnessState.AWAKE,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
index a66a136..f262df1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
@@ -24,6 +24,7 @@
import static kotlinx.coroutines.flow.FlowKt.emptyFlow;
+import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -43,6 +44,7 @@
import android.platform.test.annotations.EnableFlags;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import android.view.MotionEvent;
import android.view.View;
import android.view.ViewTreeObserver;
@@ -51,11 +53,14 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.UiEventLogger;
import com.android.internal.logging.nano.MetricsProto;
+import com.android.systemui.ExpandHelper;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor;
import com.android.systemui.classifier.FalsingCollectorFake;
import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.dump.DumpManager;
+import com.android.systemui.flags.DisableSceneContainer;
+import com.android.systemui.flags.EnableSceneContainer;
import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository;
import com.android.systemui.keyguard.shared.model.KeyguardState;
import com.android.systemui.keyguard.shared.model.TransitionStep;
@@ -171,6 +176,7 @@
@Mock private NotificationListViewBinder mViewBinder;
@Mock
private SensitiveNotificationProtectionController mSensitiveNotificationProtectionController;
+ @Mock private ExpandHelper mExpandHelper;
@Captor
private ArgumentCaptor<Runnable> mSensitiveStateListenerArgumentCaptor;
@@ -895,6 +901,50 @@
verify(mSensitiveNotificationProtectionController).registerSensitiveStateListener(any());
}
+ @Test
+ @EnableSceneContainer
+ public void onTouchEvent_stopExpandingNotification_sceneContainerEnabled() {
+ boolean touchHandled = stopExpandingNotification();
+
+ verify(mNotificationStackScrollLayout).startOverscrollAfterExpanding();
+ verify(mNotificationStackScrollLayout, never()).dispatchDownEventToScroller(any());
+ assertTrue(touchHandled);
+ }
+
+ @Test
+ @DisableSceneContainer
+ public void onTouchEvent_stopExpandingNotification_sceneContainerDisabled() {
+ stopExpandingNotification();
+
+ verify(mNotificationStackScrollLayout, never()).startOverscrollAfterExpanding();
+ verify(mNotificationStackScrollLayout).dispatchDownEventToScroller(any());
+ }
+
+ private boolean stopExpandingNotification() {
+ when(mNotificationStackScrollLayout.getExpandHelper()).thenReturn(mExpandHelper);
+ when(mNotificationStackScrollLayout.getIsExpanded()).thenReturn(true);
+ when(mNotificationStackScrollLayout.getExpandedInThisMotion()).thenReturn(true);
+ when(mNotificationStackScrollLayout.isExpandingNotification()).thenReturn(true);
+
+ when(mExpandHelper.onTouchEvent(any())).thenAnswer(i -> {
+ when(mNotificationStackScrollLayout.isExpandingNotification()).thenReturn(false);
+ return false;
+ });
+
+ initController(/* viewIsAttached= */ true);
+ NotificationStackScrollLayoutController.TouchHandler touchHandler =
+ mController.getTouchHandler();
+
+ return touchHandler.onTouchEvent(MotionEvent.obtain(
+ /* downTime= */ 0,
+ /* eventTime= */ 0,
+ MotionEvent.ACTION_DOWN,
+ 0,
+ 0,
+ /* metaState= */ 0
+ ));
+ }
+
private LogMaker logMatcher(int category, int type) {
return argThat(new LogMatcher(category, type));
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
index 939d055..0c0a2a5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
@@ -207,6 +207,7 @@
.thenReturn(mNotificationRoundnessManager);
mStackScroller.setController(mStackScrollLayoutController);
mStackScroller.setShelf(mNotificationShelf);
+ when(mStackScroller.getExpandHelper()).thenReturn(mExpandHelper);
doNothing().when(mGroupExpansionManager).collapseGroups();
doNothing().when(mExpandHelper).cancelImmediately();
@@ -1139,6 +1140,14 @@
assertFalse(mStackScroller.mHeadsUpAnimatingAway);
}
+ @Test
+ @EnableSceneContainer
+ public void finishExpanding_sceneContainerEnabled() {
+ mStackScroller.startOverscrollAfterExpanding();
+ verify(mStackScroller.getExpandHelper()).finishExpanding();
+ assertTrue(mStackScroller.getIsBeingDragged());
+ }
+
private MotionEvent captureTouchSentToSceneFramework() {
ArgumentCaptor<MotionEvent> captor = ArgumentCaptor.forClass(MotionEvent.class);
verify(mStackScrollLayoutController).sendTouchToSceneFramework(captor.capture());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
index 82725d6..a6fb718 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
@@ -394,8 +394,20 @@
}
@Test
+ fun resetViewStates_shadeCollapsed_emptyShadeViewBecomesTransparent() {
+ ambientState.expansionFraction = 0f
+ stackScrollAlgorithm.initView(context)
+ hostView.removeAllViews()
+ hostView.addView(emptyShadeView)
+
+ stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0)
+
+ assertThat(emptyShadeView.viewState.alpha).isEqualTo(0f)
+ }
+
+ @Test
fun resetViewStates_isOnKeyguard_emptyShadeViewBecomesOpaque() {
- ambientState.setStatusBarState(StatusBarState.SHADE)
+ ambientState.setStatusBarState(StatusBarState.KEYGUARD)
ambientState.fractionToShade = 0.25f
stackScrollAlgorithm.initView(context)
hostView.removeAllViews()
@@ -403,7 +415,8 @@
stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0)
- assertThat(emptyShadeView.viewState.alpha).isEqualTo(1f)
+ val expected = getContentAlpha(ambientState.fractionToShade)
+ assertThat(emptyShadeView.viewState.alpha).isEqualTo(expected)
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
index f49dc98..dc7525c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
@@ -55,6 +55,7 @@
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.keyguard.domain.interactor.BiometricUnlockInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
+import com.android.systemui.keyguard.shared.model.BiometricUnlockSource;
import com.android.systemui.keyguard.shared.model.KeyguardState;
import com.android.systemui.keyguard.shared.model.TransitionState;
import com.android.systemui.keyguard.shared.model.TransitionStep;
@@ -337,7 +338,9 @@
// WHEN we want to unlock collapse
mBiometricUnlockController.startWakeAndUnlock(
- BiometricUnlockController.MODE_UNLOCK_COLLAPSING);
+ BiometricUnlockController.MODE_UNLOCK_COLLAPSING,
+ BiometricUnlockSource.FINGERPRINT_SENSOR
+ );
verify(mStatusBarKeyguardViewManager).notifyKeyguardAuthenticated(
/* strongAuth */ eq(false));
@@ -501,7 +504,7 @@
TransitionState.STARTED
)
);
- verify(mBiometricUnlockInteractor, never()).setBiometricUnlockState(anyInt());
+ verify(mBiometricUnlockInteractor, never()).setBiometricUnlockState(anyInt(), any());
mBiometricUnlockController.consumeTransitionStepOnStartedKeyguardState(
new TransitionStep(
@@ -511,7 +514,7 @@
TransitionState.STARTED
)
);
- verify(mBiometricUnlockInteractor).setBiometricUnlockState(eq(MODE_NONE));
+ verify(mBiometricUnlockInteractor).setBiometricUnlockState(eq(MODE_NONE), eq(null));
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
index f666d8e..b9312d3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
@@ -21,9 +21,12 @@
import static android.provider.Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED;
import static android.provider.Settings.Global.HEADS_UP_ON;
+import static com.android.systemui.Flags.FLAG_KEYBOARD_SHORTCUT_HELPER_REWRITE;
import static com.android.systemui.Flags.FLAG_LIGHT_REVEAL_MIGRATION;
+import static com.android.systemui.flags.Flags.SHORTCUT_LIST_SEARCH_LAYOUT;
import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
import static com.android.systemui.statusbar.StatusBarState.SHADE;
+import static com.android.systemui.statusbar.phone.CentralSurfaces.MSG_DISMISS_KEYBOARD_SHORTCUTS_MENU;
import static com.google.common.truth.Truth.assertThat;
@@ -42,6 +45,7 @@
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import static java.util.Collections.emptySet;
@@ -52,6 +56,8 @@
import android.app.trust.TrustManager;
import android.content.BroadcastReceiver;
import android.content.IntentFilter;
+import android.content.res.Configuration;
+import android.graphics.Rect;
import android.hardware.devicestate.DeviceState;
import android.hardware.devicestate.DeviceStateManager;
import android.hardware.display.AmbientDisplayConfiguration;
@@ -73,6 +79,8 @@
import android.util.SparseArray;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
+import android.view.WindowManager;
+import android.view.WindowMetrics;
import androidx.test.filters.SmallTest;
@@ -137,6 +145,8 @@
import com.android.systemui.shade.ShadeExpansionStateManager;
import com.android.systemui.shade.ShadeLogger;
import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.KeyboardShortcutListSearch;
+import com.android.systemui.statusbar.KeyboardShortcuts;
import com.android.systemui.statusbar.KeyguardIndicationController;
import com.android.systemui.statusbar.LightRevealScrim;
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
@@ -202,6 +212,7 @@
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
+import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import java.io.ByteArrayOutputStream;
@@ -326,18 +337,21 @@
@Mock IPowerManager mPowerManagerService;
@Mock ActivityStarter mActivityStarter;
@Mock private WindowRootViewVisibilityInteractor mWindowRootViewVisibilityInteractor;
+ @Mock private KeyboardShortcuts mKeyboardShortcuts;
+ @Mock private KeyboardShortcutListSearch mKeyboardShortcutListSearch;
private ShadeController mShadeController;
private final FakeSystemClock mFakeSystemClock = new FakeSystemClock();
private final FakeGlobalSettings mFakeGlobalSettings = new FakeGlobalSettings();
private final SystemSettings mSystemSettings = new FakeSettings();
private final FakeEventLog mFakeEventLog = new FakeEventLog();
- private final FakeExecutor mMainExecutor = new FakeExecutor(mFakeSystemClock);
+ private FakeExecutor mMainExecutor = new FakeExecutor(mFakeSystemClock);
private final FakeExecutor mUiBgExecutor = new FakeExecutor(mFakeSystemClock);
private final FakeFeatureFlags mFeatureFlags = new FakeFeatureFlags();
private final InitController mInitController = new InitController();
private final DumpManager mDumpManager = new DumpManager();
private final ScreenLifecycle mScreenLifecycle = new ScreenLifecycle(mDumpManager);
+ private MessageRouterImpl mMessageRouter = new MessageRouterImpl(mMainExecutor);
private final BrightnessMirrorShowingInteractor mBrightnessMirrorShowingInteractor =
mKosmos.getBrightnessMirrorShowingInteractor();
@@ -347,7 +361,7 @@
MockitoAnnotations.initMocks(this);
// Set default value to avoid IllegalStateException.
- mFeatureFlags.set(Flags.SHORTCUT_LIST_SEARCH_LAYOUT, false);
+ mFeatureFlags.set(SHORTCUT_LIST_SEARCH_LAYOUT, false);
mSetFlagsRule.enableFlags(FLAG_LIGHT_REVEAL_MIGRATION);
// Turn AOD on and toggle feature flag for jank fixes
mFeatureFlags.set(Flags.ZJ_285570694_LOCKSCREEN_TRANSITION_FROM_AOD, true);
@@ -462,6 +476,16 @@
}
private void createCentralSurfaces() {
+ mMainExecutor = new FakeExecutor(mFakeSystemClock);
+ mMessageRouter = new MessageRouterImpl(mMainExecutor);
+ mKeyboardShortcuts = mock(KeyboardShortcuts.class);
+ mKeyboardShortcutListSearch = mock(KeyboardShortcutListSearch.class);
+ // Test setup for legacy version
+ mKeyboardShortcuts.mContext = mContext;
+ mKeyboardShortcutListSearch.mContext = mContext;
+ KeyboardShortcuts.sInstance = mKeyboardShortcuts;
+ KeyboardShortcutListSearch.sInstance = mKeyboardShortcutListSearch;
+
ConfigurationController configurationController = new ConfigurationControllerImpl(mContext);
mCentralSurfaces = new CentralSurfacesImpl(
mContext,
@@ -554,7 +578,7 @@
mFeatureFlags,
mKeyguardUnlockAnimationController,
mMainExecutor,
- new MessageRouterImpl(mMainExecutor),
+ mMessageRouter,
mWallpaperManager,
Optional.of(mStartingSurface),
mActivityTransitionAnimator,
@@ -1126,6 +1150,194 @@
verify(mScrimController, never()).transitionTo(eq(ScrimState.BRIGHTNESS_MIRROR), any());
}
+ @Test
+ public void dismissKeyboardShortcuts_largeScreen_bothFlagsEnabled_doesNotDismissAny() {
+ switchToLargeScreen();
+ mFeatureFlags.set(SHORTCUT_LIST_SEARCH_LAYOUT, true);
+ mSetFlagsRule.enableFlags(FLAG_KEYBOARD_SHORTCUT_HELPER_REWRITE);
+ createCentralSurfaces();
+
+ dismissKeyboardShortcuts();
+
+ verifyNoMoreInteractions(mKeyboardShortcuts, mKeyboardShortcutListSearch);
+ }
+
+ @Test
+ public void dismissKeyboardShortcuts_largeScreen_newFlagsDisabled_dismissesTabletVersion() {
+ switchToLargeScreen();
+ mFeatureFlags.set(SHORTCUT_LIST_SEARCH_LAYOUT, true);
+ mSetFlagsRule.disableFlags(FLAG_KEYBOARD_SHORTCUT_HELPER_REWRITE);
+ createCentralSurfaces();
+
+ dismissKeyboardShortcuts();
+
+ verify(mKeyboardShortcutListSearch).dismissKeyboardShortcuts();
+ }
+
+ @Test
+ public void dismissKeyboardShortcuts_largeScreen_bothFlagsDisabled_dismissesPhoneVersion() {
+ switchToLargeScreen();
+ mFeatureFlags.set(SHORTCUT_LIST_SEARCH_LAYOUT, false);
+ mSetFlagsRule.disableFlags(FLAG_KEYBOARD_SHORTCUT_HELPER_REWRITE);
+ createCentralSurfaces();
+
+ dismissKeyboardShortcuts();
+
+ verify(mKeyboardShortcuts).dismissKeyboardShortcuts();
+ verifyNoMoreInteractions(mKeyboardShortcutListSearch);
+ }
+
+ @Test
+ public void dismissKeyboardShortcuts_smallScreen_bothFlagsEnabled_doesNotDismissAny() {
+ switchToSmallScreen();
+ mFeatureFlags.set(SHORTCUT_LIST_SEARCH_LAYOUT, true);
+ mSetFlagsRule.enableFlags(FLAG_KEYBOARD_SHORTCUT_HELPER_REWRITE);
+ createCentralSurfaces();
+
+ dismissKeyboardShortcuts();
+
+ verifyNoMoreInteractions(mKeyboardShortcuts, mKeyboardShortcutListSearch);
+ }
+
+ @Test
+ public void dismissKeyboardShortcuts_smallScreen_newFlagsDisabled_dismissesPhoneVersion() {
+ switchToSmallScreen();
+ mFeatureFlags.set(SHORTCUT_LIST_SEARCH_LAYOUT, true);
+ mSetFlagsRule.disableFlags(FLAG_KEYBOARD_SHORTCUT_HELPER_REWRITE);
+ createCentralSurfaces();
+
+ dismissKeyboardShortcuts();
+
+ verify(mKeyboardShortcuts).dismissKeyboardShortcuts();
+ verifyNoMoreInteractions(mKeyboardShortcutListSearch);
+ }
+
+ @Test
+ public void dismissKeyboardShortcuts_smallScreen_bothFlagsDisabled_dismissesPhoneVersion() {
+ switchToSmallScreen();
+ mFeatureFlags.set(SHORTCUT_LIST_SEARCH_LAYOUT, false);
+ mSetFlagsRule.disableFlags(FLAG_KEYBOARD_SHORTCUT_HELPER_REWRITE);
+ createCentralSurfaces();
+
+ dismissKeyboardShortcuts();
+
+ verify(mKeyboardShortcuts).dismissKeyboardShortcuts();
+ verifyNoMoreInteractions(mKeyboardShortcutListSearch);
+ }
+
+ @Test
+ public void toggleKeyboardShortcuts_largeScreen_bothFlagsEnabled_doesNotTogglesAny() {
+ switchToLargeScreen();
+ mFeatureFlags.set(SHORTCUT_LIST_SEARCH_LAYOUT, true);
+ mSetFlagsRule.enableFlags(FLAG_KEYBOARD_SHORTCUT_HELPER_REWRITE);
+ createCentralSurfaces();
+
+ int deviceId = 321;
+ toggleKeyboardShortcuts(/* deviceId= */ deviceId);
+
+ verifyNoMoreInteractions(mKeyboardShortcuts, mKeyboardShortcutListSearch);
+ }
+
+ @Test
+ public void toggleKeyboardShortcuts_largeScreen_newFlagsDisabled_togglesTabletVersion() {
+ switchToLargeScreen();
+ mFeatureFlags.set(SHORTCUT_LIST_SEARCH_LAYOUT, true);
+ mSetFlagsRule.disableFlags(FLAG_KEYBOARD_SHORTCUT_HELPER_REWRITE);
+ createCentralSurfaces();
+
+ int deviceId = 654;
+ toggleKeyboardShortcuts(deviceId);
+
+ verify(mKeyboardShortcutListSearch).showKeyboardShortcuts(deviceId);
+ verifyNoMoreInteractions(mKeyboardShortcuts);
+ }
+
+ @Test
+ public void toggleKeyboardShortcuts_largeScreen_bothFlagsDisabled_togglesPhoneVersion() {
+ switchToLargeScreen();
+ mFeatureFlags.set(SHORTCUT_LIST_SEARCH_LAYOUT, false);
+ mSetFlagsRule.disableFlags(FLAG_KEYBOARD_SHORTCUT_HELPER_REWRITE);
+ createCentralSurfaces();
+
+ int deviceId = 987;
+ toggleKeyboardShortcuts(deviceId);
+
+ verify(mKeyboardShortcuts).showKeyboardShortcuts(deviceId);
+ verifyNoMoreInteractions(mKeyboardShortcutListSearch);
+ }
+
+ @Test
+ public void toggleKeyboardShortcuts_smallScreen_bothFlagsEnabled_doesNotToggleAny() {
+ switchToSmallScreen();
+ mFeatureFlags.set(SHORTCUT_LIST_SEARCH_LAYOUT, true);
+ mSetFlagsRule.enableFlags(FLAG_KEYBOARD_SHORTCUT_HELPER_REWRITE);
+ createCentralSurfaces();
+
+ int deviceId = 789;
+ toggleKeyboardShortcuts(/* deviceId= */ deviceId);
+
+ verifyNoMoreInteractions(mKeyboardShortcuts, mKeyboardShortcutListSearch);
+ }
+
+ @Test
+ public void toggleKeyboardShortcuts_smallScreen_newFlagsDisabled_togglesPhoneVersion() {
+ switchToSmallScreen();
+ mFeatureFlags.set(SHORTCUT_LIST_SEARCH_LAYOUT, true);
+ mSetFlagsRule.disableFlags(FLAG_KEYBOARD_SHORTCUT_HELPER_REWRITE);
+ createCentralSurfaces();
+
+ int deviceId = 456;
+ toggleKeyboardShortcuts(deviceId);
+
+ verify(mKeyboardShortcuts).showKeyboardShortcuts(deviceId);
+ verifyNoMoreInteractions(mKeyboardShortcutListSearch);
+ }
+
+ @Test
+ public void toggleKeyboardShortcuts_smallScreen_bothFlagsDisabled_togglesPhoneVersion() {
+ switchToSmallScreen();
+ mFeatureFlags.set(SHORTCUT_LIST_SEARCH_LAYOUT, false);
+ mSetFlagsRule.disableFlags(FLAG_KEYBOARD_SHORTCUT_HELPER_REWRITE);
+ createCentralSurfaces();
+
+ int deviceId = 123;
+ toggleKeyboardShortcuts(deviceId);
+
+ verify(mKeyboardShortcuts).showKeyboardShortcuts(deviceId);
+ verifyNoMoreInteractions(mKeyboardShortcutListSearch);
+ }
+
+ private void dismissKeyboardShortcuts() {
+ mMessageRouter.sendMessage(MSG_DISMISS_KEYBOARD_SHORTCUTS_MENU);
+ mMainExecutor.runAllReady();
+ }
+
+ private void toggleKeyboardShortcuts(int deviceId) {
+ mMessageRouter.sendMessage(new CentralSurfaces.KeyboardShortcutsMessage(deviceId));
+ mMainExecutor.runAllReady();
+ }
+
+ private void switchToLargeScreen() {
+ switchToScreenSize(1280, 800);
+ }
+
+ private void switchToSmallScreen() {
+ switchToScreenSize(504, 1122);
+ }
+
+ private void switchToScreenSize(int widthDp, int heightDp) {
+ WindowMetrics windowMetrics = Mockito.mock(WindowMetrics.class);
+ WindowManager windowManager = Mockito.mock(WindowManager.class);
+
+ Configuration configuration = new Configuration();
+ configuration.densityDpi = DisplayMetrics.DENSITY_DEFAULT;
+ mContext.getOrCreateTestableResources().overrideConfiguration(configuration);
+
+ when(windowMetrics.getBounds()).thenReturn(new Rect(0, 0, widthDp, heightDp));
+ when(windowManager.getCurrentWindowMetrics()).thenReturn(windowMetrics);
+ mContext.addMockSystemService(WindowManager.class, windowManager);
+ }
+
/**
* Configures the appropriate mocks and then calls {@link CentralSurfacesImpl#updateIsKeyguard}
* to reconfigure the keyguard to reflect the requested showing/occluded states.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.java
index 8e9840a..dfee737 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.java
@@ -178,6 +178,7 @@
keyguardTransitionInteractor,
() -> mKosmos.getSceneInteractor(),
() -> mKosmos.getFromGoneTransitionInteractor(),
+ () -> mKosmos.getFromLockscreenTransitionInteractor(),
() -> mKosmos.getSharedNotificationContainerInteractor(),
mTestScope);
mViewModel =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
index e38e31d..6b3c005 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
@@ -187,8 +187,7 @@
when(mBouncerViewDelegate.getBackCallback()).thenReturn(mBouncerViewDelegateBackCallback);
mSetFlagsRule.disableFlags(
com.android.systemui.Flags.FLAG_DEVICE_ENTRY_UDFPS_REFACTOR,
- com.android.systemui.Flags.FLAG_KEYGUARD_WM_STATE_REFACTOR,
- com.android.systemui.Flags.FLAG_REFACTOR_KEYGUARD_DISMISS_INTENT
+ com.android.systemui.Flags.FLAG_KEYGUARD_WM_STATE_REFACTOR
);
when(mNotificationShadeWindowController.getWindowRootView())
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/DeviceBasedSatelliteRepositorySwitcherTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/DeviceBasedSatelliteRepositorySwitcherTest.kt
new file mode 100644
index 0000000..7ca3b1c
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/DeviceBasedSatelliteRepositorySwitcherTest.kt
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.satellite.data
+
+import android.telephony.satellite.SatelliteManager
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.demomode.DemoMode
+import com.android.systemui.demomode.DemoModeController
+import com.android.systemui.log.core.FakeLogBuffer
+import com.android.systemui.statusbar.pipeline.satellite.data.demo.DemoDeviceBasedSatelliteDataSource
+import com.android.systemui.statusbar.pipeline.satellite.data.demo.DemoDeviceBasedSatelliteRepository
+import com.android.systemui.statusbar.pipeline.satellite.data.prod.DeviceBasedSatelliteRepositoryImpl
+import com.android.systemui.statusbar.pipeline.satellite.shared.model.SatelliteConnectionState
+import com.android.systemui.util.mockito.kotlinArgumentCaptor
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
+import com.android.systemui.util.time.FakeSystemClock
+import com.google.common.truth.Truth.assertThat
+import java.util.Optional
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.mockito.Mockito.verify
+
+@SmallTest
+class DeviceBasedSatelliteRepositorySwitcherTest : SysuiTestCase() {
+ private val testDispatcher = StandardTestDispatcher()
+ private val testScope = TestScope(testDispatcher)
+
+ private val demoModeController =
+ mock<DemoModeController>().apply { whenever(this.isInDemoMode).thenReturn(false) }
+ private val satelliteManager = mock<SatelliteManager>()
+ private val systemClock = FakeSystemClock()
+
+ private val realImpl =
+ DeviceBasedSatelliteRepositoryImpl(
+ Optional.of(satelliteManager),
+ testDispatcher,
+ testScope.backgroundScope,
+ FakeLogBuffer.Factory.create(),
+ systemClock,
+ )
+ private val demoDataSource =
+ mock<DemoDeviceBasedSatelliteDataSource>().also {
+ whenever(it.satelliteEvents)
+ .thenReturn(
+ MutableStateFlow(
+ DemoDeviceBasedSatelliteDataSource.DemoSatelliteEvent(
+ connectionState = SatelliteConnectionState.Unknown,
+ signalStrength = 0,
+ )
+ )
+ )
+ }
+ private val demoImpl =
+ DemoDeviceBasedSatelliteRepository(demoDataSource, testScope.backgroundScope)
+
+ private val underTest =
+ DeviceBasedSatelliteRepositorySwitcher(
+ realImpl,
+ demoImpl,
+ demoModeController,
+ testScope.backgroundScope,
+ )
+
+ @OptIn(ExperimentalCoroutinesApi::class)
+ @Test
+ fun switcherActiveRepo_updatesWhenDemoModeChanges() =
+ testScope.runTest {
+ assertThat(underTest.activeRepo.value).isSameInstanceAs(realImpl)
+
+ val latest by collectLastValue(underTest.activeRepo)
+ runCurrent()
+
+ startDemoMode()
+
+ assertThat(latest).isSameInstanceAs(demoImpl)
+
+ finishDemoMode()
+
+ assertThat(latest).isSameInstanceAs(realImpl)
+ }
+
+ private fun startDemoMode() {
+ whenever(demoModeController.isInDemoMode).thenReturn(true)
+ getDemoModeCallback().onDemoModeStarted()
+ }
+
+ private fun finishDemoMode() {
+ whenever(demoModeController.isInDemoMode).thenReturn(false)
+ getDemoModeCallback().onDemoModeFinished()
+ }
+
+ private fun getDemoModeCallback(): DemoMode {
+ val captor = kotlinArgumentCaptor<DemoMode>()
+ verify(demoModeController).addCallback(captor.capture())
+ return captor.value
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/demo/DemoDeviceBasedSatelliteRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/demo/DemoDeviceBasedSatelliteRepositoryTest.kt
new file mode 100644
index 0000000..f77fd19
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/demo/DemoDeviceBasedSatelliteRepositoryTest.kt
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.satellite.data.demo
+
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.statusbar.pipeline.satellite.shared.model.SatelliteConnectionState
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import kotlin.test.Test
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+
+@SmallTest
+class DemoDeviceBasedSatelliteRepositoryTest : SysuiTestCase() {
+
+ private val testDispatcher = StandardTestDispatcher()
+ private val testScope = TestScope(testDispatcher)
+
+ private val fakeSatelliteEvents =
+ MutableStateFlow(
+ DemoDeviceBasedSatelliteDataSource.DemoSatelliteEvent(
+ connectionState = SatelliteConnectionState.Unknown,
+ signalStrength = 0,
+ )
+ )
+
+ private lateinit var dataSource: DemoDeviceBasedSatelliteDataSource
+
+ private lateinit var underTest: DemoDeviceBasedSatelliteRepository
+
+ @Before
+ fun setUp() {
+ dataSource =
+ mock<DemoDeviceBasedSatelliteDataSource>().also {
+ whenever(it.satelliteEvents).thenReturn(fakeSatelliteEvents)
+ }
+
+ underTest = DemoDeviceBasedSatelliteRepository(dataSource, testScope.backgroundScope)
+ }
+
+ @Test
+ fun startProcessing_getsNewUpdates() =
+ testScope.runTest {
+ val latestConnection by collectLastValue(underTest.connectionState)
+ val latestSignalStrength by collectLastValue(underTest.signalStrength)
+
+ underTest.startProcessingCommands()
+
+ fakeSatelliteEvents.value =
+ DemoDeviceBasedSatelliteDataSource.DemoSatelliteEvent(
+ connectionState = SatelliteConnectionState.On,
+ signalStrength = 3,
+ )
+
+ assertThat(latestConnection).isEqualTo(SatelliteConnectionState.On)
+ assertThat(latestSignalStrength).isEqualTo(3)
+
+ fakeSatelliteEvents.value =
+ DemoDeviceBasedSatelliteDataSource.DemoSatelliteEvent(
+ connectionState = SatelliteConnectionState.Connected,
+ signalStrength = 4,
+ )
+
+ assertThat(latestConnection).isEqualTo(SatelliteConnectionState.Connected)
+ assertThat(latestSignalStrength).isEqualTo(4)
+ }
+
+ @Test
+ fun stopProcessing_stopsGettingUpdates() =
+ testScope.runTest {
+ val latestConnection by collectLastValue(underTest.connectionState)
+ val latestSignalStrength by collectLastValue(underTest.signalStrength)
+
+ underTest.startProcessingCommands()
+
+ fakeSatelliteEvents.value =
+ DemoDeviceBasedSatelliteDataSource.DemoSatelliteEvent(
+ connectionState = SatelliteConnectionState.On,
+ signalStrength = 3,
+ )
+ assertThat(latestConnection).isEqualTo(SatelliteConnectionState.On)
+ assertThat(latestSignalStrength).isEqualTo(3)
+
+ underTest.stopProcessingCommands()
+
+ // WHEN new values are emitted
+ fakeSatelliteEvents.value =
+ DemoDeviceBasedSatelliteDataSource.DemoSatelliteEvent(
+ connectionState = SatelliteConnectionState.Connected,
+ signalStrength = 4,
+ )
+
+ // THEN they're not collected because we stopped processing commands, so the old values
+ // are still present
+ assertThat(latestConnection).isEqualTo(SatelliteConnectionState.On)
+ assertThat(latestSignalStrength).isEqualTo(3)
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImplTest.kt
index 77e48bff..6b0ad4b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImplTest.kt
@@ -156,7 +156,7 @@
verify(satelliteManager).registerForNtnSignalStrengthChanged(any(), capture())
}
- assertThat(latest).isNull()
+ assertThat(latest).isEqualTo(0)
callback.onNtnSignalStrengthChanged(NtnSignalStrength(1))
assertThat(latest).isEqualTo(1)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractorTest.kt
index c4ab943..405e3ed 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractorTest.kt
@@ -250,7 +250,7 @@
@Test
@EnableFlags(FLAG_OEM_ENABLED_SATELLITE_FLAG)
- fun areAllConnectionsOutOfService_twoConnectionsOos_yes() =
+ fun areAllConnectionsOutOfService_twoConnectionsOos_nonNtn_yes() =
testScope.runTest {
val latest by collectLastValue(underTest.areAllConnectionsOutOfService)
@@ -258,11 +258,13 @@
val i1 = iconsInteractor.getMobileConnectionInteractorForSubId(1)
val i2 = iconsInteractor.getMobileConnectionInteractorForSubId(2)
- // WHEN all of the connections are OOS
+ // WHEN all of the connections are OOS and none are NTN
i1.isInService.value = false
i1.isEmergencyOnly.value = false
+ i1.isNonTerrestrial.value = false
i2.isInService.value = false
i2.isEmergencyOnly.value = false
+ i2.isNonTerrestrial.value = false
// THEN the value is propagated to this interactor
assertThat(latest).isTrue()
@@ -270,7 +272,31 @@
@Test
@EnableFlags(FLAG_OEM_ENABLED_SATELLITE_FLAG)
- fun areAllConnectionsOutOfService_oneConnectionOos_yes() =
+ fun areAllConnectionsOutOfService_twoConnectionsOos_oneNtn_no() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.areAllConnectionsOutOfService)
+
+ // GIVEN, 2 connections
+ val i1 = iconsInteractor.getMobileConnectionInteractorForSubId(1)
+ val i2 = iconsInteractor.getMobileConnectionInteractorForSubId(2)
+
+ // WHEN all of the connections are OOS and one is NTN
+ i1.isInService.value = false
+ i1.isEmergencyOnly.value = false
+ i1.isNonTerrestrial.value = false
+ i2.isInService.value = false
+ i2.isEmergencyOnly.value = false
+
+ // sub2 is non terrestrial, consider it connected for the sake of the iconography
+ i2.isNonTerrestrial.value = true
+
+ // THEN the value is propagated to this interactor
+ assertThat(latest).isFalse()
+ }
+
+ @Test
+ @EnableFlags(FLAG_OEM_ENABLED_SATELLITE_FLAG)
+ fun areAllConnectionsOutOfService_oneConnectionOos_nonNtn_yes() =
testScope.runTest {
val latest by collectLastValue(underTest.areAllConnectionsOutOfService)
@@ -280,6 +306,7 @@
// WHEN all of the connections are OOS
i1.isInService.value = false
i1.isEmergencyOnly.value = false
+ i1.isNonTerrestrial.value = false
// THEN the value is propagated to this interactor
assertThat(latest).isTrue()
@@ -287,7 +314,25 @@
@Test
@EnableFlags(FLAG_OEM_ENABLED_SATELLITE_FLAG)
- fun areAllConnectionsOutOfService_oneConnectionInService_no() =
+ fun areAllConnectionsOutOfService_oneConnectionOos_ntn_yes() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.areAllConnectionsOutOfService)
+
+ // GIVEN, 1 connection
+ val i1 = iconsInteractor.getMobileConnectionInteractorForSubId(1)
+
+ // WHEN all of the connections are OOS
+ i1.isInService.value = false
+ i1.isEmergencyOnly.value = false
+ i1.isNonTerrestrial.value = true
+
+ // THEN the value is propagated to this interactor
+ assertThat(latest).isFalse()
+ }
+
+ @Test
+ @EnableFlags(FLAG_OEM_ENABLED_SATELLITE_FLAG)
+ fun areAllConnectionsOutOfService_oneConnectionInService_nonNtn_no() =
testScope.runTest {
val latest by collectLastValue(underTest.areAllConnectionsOutOfService)
@@ -296,6 +341,7 @@
// WHEN all of the connections are NOT OOS
i1.isInService.value = true
+ i1.isNonTerrestrial.value = false
// THEN the value is propagated to this interactor
assertThat(latest).isFalse()
@@ -303,7 +349,24 @@
@Test
@EnableFlags(FLAG_OEM_ENABLED_SATELLITE_FLAG)
- fun areAllConnectionsOutOfService_twoConnectionsOneInService_no() =
+ fun areAllConnectionsOutOfService_oneConnectionInService_ntn_no() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.areAllConnectionsOutOfService)
+
+ // GIVEN, 1 connection
+ val i1 = iconsInteractor.getMobileConnectionInteractorForSubId(1)
+
+ // WHEN all of the connections are NOT OOS
+ i1.isInService.value = true
+ i1.isNonTerrestrial.value = true
+
+ // THEN the value is propagated to this interactor
+ assertThat(latest).isFalse()
+ }
+
+ @Test
+ @EnableFlags(FLAG_OEM_ENABLED_SATELLITE_FLAG)
+ fun areAllConnectionsOutOfService_twoConnectionsOneInService_nonNtn_no() =
testScope.runTest {
val latest by collectLastValue(underTest.areAllConnectionsOutOfService)
@@ -313,7 +376,9 @@
// WHEN at least 1 connection is NOT OOS.
i1.isInService.value = false
+ i1.isNonTerrestrial.value = false
i2.isInService.value = true
+ i2.isNonTerrestrial.value = false
// THEN the value is propagated to this interactor
assertThat(latest).isFalse()
@@ -321,7 +386,7 @@
@Test
@EnableFlags(FLAG_OEM_ENABLED_SATELLITE_FLAG)
- fun areAllConnectionsOutOfService_twoConnectionsInService_no() =
+ fun areAllConnectionsOutOfService_twoConnectionsInService_nonNtn_no() =
testScope.runTest {
val latest by collectLastValue(underTest.areAllConnectionsOutOfService)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerTest.java
index 9d4f1fc..ed8843b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerTest.java
@@ -38,13 +38,13 @@
import android.os.PowerSaveState;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
-import android.view.View;
import androidx.test.filters.SmallTest;
import com.android.dx.mockito.inline.extended.StaticInOrder;
import com.android.settingslib.fuelgauge.BatterySaverUtils;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.animation.Expandable;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.demomode.DemoModeController;
import com.android.systemui.dump.DumpManager;
@@ -72,7 +72,7 @@
@Mock private PowerManager mPowerManager;
@Mock private BroadcastDispatcher mBroadcastDispatcher;
@Mock private DemoModeController mDemoModeController;
- @Mock private View mView;
+ @Mock private Expandable mExpandable;
@Mock private UsbPort mUsbPort;
@Mock private UsbManager mUsbManager;
@Mock private UsbPortStatus mUsbPortStatus;
@@ -175,8 +175,8 @@
@Test
public void testBatteryUtilsCalledOnSetPowerSaveMode() {
- mBatteryController.setPowerSaveMode(true, mView);
- mBatteryController.setPowerSaveMode(false, mView);
+ mBatteryController.setPowerSaveMode(true, mExpandable);
+ mBatteryController.setPowerSaveMode(false, mExpandable);
StaticInOrder inOrder = inOrder(staticMockMarker(BatterySaverUtils.class));
inOrder.verify(() -> BatterySaverUtils.setPowerSaveMode(getContext(), true, true,
@@ -187,21 +187,21 @@
@Test
public void testSaveViewReferenceWhenSettingPowerSaveMode() {
- mBatteryController.setPowerSaveMode(false, mView);
+ mBatteryController.setPowerSaveMode(false, mExpandable);
- Assert.assertNull(mBatteryController.getLastPowerSaverStartView());
+ Assert.assertNull(mBatteryController.getLastPowerSaverStartExpandable());
- mBatteryController.setPowerSaveMode(true, mView);
+ mBatteryController.setPowerSaveMode(true, mExpandable);
- Assert.assertSame(mView, mBatteryController.getLastPowerSaverStartView().get());
+ Assert.assertSame(mExpandable, mBatteryController.getLastPowerSaverStartExpandable().get());
}
@Test
public void testClearViewReference() {
- mBatteryController.setPowerSaveMode(true, mView);
- mBatteryController.clearLastPowerSaverStartView();
+ mBatteryController.setPowerSaveMode(true, mExpandable);
+ mBatteryController.clearLastPowerSaverStartExpandable();
- Assert.assertNull(mBatteryController.getLastPowerSaverStartView());
+ Assert.assertNull(mBatteryController.getLastPowerSaverStartExpandable());
}
@Test
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/accessibility/data/repository/FakeOneHandedModeRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/accessibility/data/repository/FakeOneHandedModeRepository.kt
new file mode 100644
index 0000000..ac135af
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/accessibility/data/repository/FakeOneHandedModeRepository.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.accessibility.data.repository
+
+import android.os.UserHandle
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+
+class FakeOneHandedModeRepository : OneHandedModeRepository {
+ private val userMap = mutableMapOf<Int, MutableStateFlow<Boolean>>()
+
+ override fun isEnabled(userHandle: UserHandle): StateFlow<Boolean> {
+ return getFlow(userHandle.identifier)
+ }
+
+ override suspend fun setIsEnabled(isEnabled: Boolean, userHandle: UserHandle): Boolean {
+ getFlow(userHandle.identifier).value = isEnabled
+ return true
+ }
+
+ /** initializes the flow if already not */
+ private fun getFlow(userId: Int): MutableStateFlow<Boolean> {
+ return userMap.getOrPut(userId) { MutableStateFlow(false) }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/shared/model/GridLayoutTypeKey.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/accessibility/data/repository/OneHandedModeRepositoryKosmos.kt
similarity index 63%
copy from packages/SystemUI/src/com/android/systemui/qs/panels/shared/model/GridLayoutTypeKey.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/accessibility/data/repository/OneHandedModeRepositoryKosmos.kt
index 0dbaaba..9ee200a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/shared/model/GridLayoutTypeKey.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/accessibility/data/repository/OneHandedModeRepositoryKosmos.kt
@@ -14,15 +14,9 @@
* limitations under the License.
*/
-package com.android.systemui.qs.panels.shared.model
+package com.android.systemui.accessibility.data.repository
-import dagger.MapKey
-import kotlin.reflect.KClass
+import com.android.systemui.kosmos.Kosmos
-/**
- * Dagger map key to associate a [GridLayoutType] with its
- * [com.android.systemui.qs.panels.ui.compose.GridLayout].
- */
-@Retention(AnnotationRetention.RUNTIME)
-@MapKey
-annotation class GridLayoutTypeKey(val value: KClass<out GridLayoutType>)
+val Kosmos.fakeOneHandedModeRepository by Kosmos.Fixture { FakeOneHandedModeRepository() }
+val Kosmos.oneHandedModeRepository by Kosmos.Fixture { fakeOneHandedModeRepository }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakePromptRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakePromptRepository.kt
index 2e2cf9a..0975687 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakePromptRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakePromptRepository.kt
@@ -81,7 +81,8 @@
com.android.systemui.Flags.constraintBp() &&
!Utils.isBiometricAllowed(promptInfo) &&
Utils.isDeviceCredentialAllowed(promptInfo) &&
- promptInfo.contentView != null
+ promptInfo.contentView != null &&
+ !promptInfo.isContentViewMoreOptionsButtonUsed
_showBpWithoutIconForCredential.value = showBpForCredential && !hasCredentialViewShown
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalRepository.kt
index 9f5c6b8..d958bae 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalRepository.kt
@@ -23,6 +23,7 @@
) : CommunalRepository {
override fun changeScene(toScene: SceneKey, transitionKey: TransitionKey?) {
this.currentScene.value = toScene
+ this._transitionState.value = flowOf(ObservableTransitionState.Idle(toScene))
}
private val defaultTransitionState = ObservableTransitionState.Idle(CommunalScenes.Default)
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalInteractorKosmos.kt
index 3dd382f..3fe6973 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalInteractorKosmos.kt
@@ -23,14 +23,15 @@
import com.android.systemui.communal.data.repository.communalRepository
import com.android.systemui.communal.data.repository.communalWidgetRepository
import com.android.systemui.communal.widgets.EditWidgetsActivityStarter
-import com.android.systemui.dock.fakeDockManager
import com.android.systemui.flags.Flags
import com.android.systemui.flags.fakeFeatureFlagsClassic
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
+import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.Kosmos.Fixture
import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.kosmos.testDispatcher
import com.android.systemui.log.logcatLogBuffer
import com.android.systemui.plugins.activityStarter
import com.android.systemui.scene.domain.interactor.sceneInteractor
@@ -42,6 +43,7 @@
val Kosmos.communalInteractor by Fixture {
CommunalInteractor(
applicationScope = applicationCoroutineScope,
+ bgDispatcher = testDispatcher,
broadcastDispatcher = broadcastDispatcher,
communalRepository = communalRepository,
widgetRepository = communalWidgetRepository,
@@ -49,13 +51,13 @@
mediaRepository = communalMediaRepository,
smartspaceRepository = smartspaceRepository,
keyguardInteractor = keyguardInteractor,
+ keyguardTransitionInteractor = keyguardTransitionInteractor,
communalSettingsInteractor = communalSettingsInteractor,
appWidgetHost = mock(),
editWidgetsActivityStarter = editWidgetsActivityStarter,
userTracker = userTracker,
activityStarter = activityStarter,
userManager = userManager,
- dockManager = fakeDockManager,
sceneInteractor = sceneInteractor,
logBuffer = logcatLogBuffer("CommunalInteractor"),
tableLogBuffer = mock(),
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/shared/model/GridLayoutTypeKey.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/shortcut/FakeShortcutHelperStartActivity.kt
similarity index 63%
copy from packages/SystemUI/src/com/android/systemui/qs/panels/shared/model/GridLayoutTypeKey.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/shortcut/FakeShortcutHelperStartActivity.kt
index 0dbaaba..3190171 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/shared/model/GridLayoutTypeKey.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/shortcut/FakeShortcutHelperStartActivity.kt
@@ -14,15 +14,15 @@
* limitations under the License.
*/
-package com.android.systemui.qs.panels.shared.model
+package com.android.systemui.keyboard.shortcut
-import dagger.MapKey
-import kotlin.reflect.KClass
+import android.content.Intent
-/**
- * Dagger map key to associate a [GridLayoutType] with its
- * [com.android.systemui.qs.panels.ui.compose.GridLayout].
- */
-@Retention(AnnotationRetention.RUNTIME)
-@MapKey
-annotation class GridLayoutTypeKey(val value: KClass<out GridLayoutType>)
+class FakeShortcutHelperStartActivity : (Intent) -> Unit {
+
+ val startIntents = mutableListOf<Intent>()
+
+ override fun invoke(intent: Intent) {
+ startIntents += intent
+ }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/shortcut/KeyboardShortcutHelperKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/shortcut/KeyboardShortcutHelperKosmos.kt
new file mode 100644
index 0000000..38f2a56
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/shortcut/KeyboardShortcutHelperKosmos.kt
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyboard.shortcut
+
+import android.content.applicationContext
+import com.android.systemui.broadcast.broadcastDispatcher
+import com.android.systemui.keyboard.shortcut.data.repository.ShortcutHelperRepository
+import com.android.systemui.keyboard.shortcut.data.repository.ShortcutHelperTestHelper
+import com.android.systemui.keyboard.shortcut.domain.interactor.ShortcutHelperInteractor
+import com.android.systemui.keyboard.shortcut.ui.ShortcutHelperActivityStarter
+import com.android.systemui.keyboard.shortcut.ui.viewmodel.ShortcutHelperViewModel
+import com.android.systemui.keyguard.data.repository.fakeCommandQueue
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.kosmos.testDispatcher
+
+val Kosmos.shortcutHelperRepository by
+ Kosmos.Fixture { ShortcutHelperRepository(fakeCommandQueue, broadcastDispatcher) }
+
+val Kosmos.shortcutHelperTestHelper by
+ Kosmos.Fixture {
+ ShortcutHelperTestHelper(
+ shortcutHelperRepository,
+ applicationContext,
+ broadcastDispatcher,
+ fakeCommandQueue
+ )
+ }
+
+val Kosmos.shortcutHelperInteractor by
+ Kosmos.Fixture { ShortcutHelperInteractor(shortcutHelperRepository) }
+
+val Kosmos.shortcutHelperViewModel by
+ Kosmos.Fixture { ShortcutHelperViewModel(testDispatcher, shortcutHelperInteractor) }
+
+val Kosmos.fakeShortcutHelperStartActivity by Kosmos.Fixture { FakeShortcutHelperStartActivity() }
+
+val Kosmos.shortcutHelperActivityStarter by
+ Kosmos.Fixture {
+ ShortcutHelperActivityStarter(
+ applicationContext,
+ applicationCoroutineScope,
+ shortcutHelperViewModel,
+ fakeShortcutHelperStartActivity,
+ )
+ }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/shortcut/data/repository/ShortcutHelperTestHelper.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/shortcut/data/repository/ShortcutHelperTestHelper.kt
new file mode 100644
index 0000000..772ce41
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/shortcut/data/repository/ShortcutHelperTestHelper.kt
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyboard.shortcut.data.repository
+
+import android.content.Context
+import android.content.Intent
+import com.android.systemui.broadcast.FakeBroadcastDispatcher
+import com.android.systemui.keyguard.data.repository.FakeCommandQueue
+
+class ShortcutHelperTestHelper(
+ repo: ShortcutHelperRepository,
+ private val context: Context,
+ private val fakeBroadcastDispatcher: FakeBroadcastDispatcher,
+ private val fakeCommandQueue: FakeCommandQueue,
+) {
+
+ init {
+ repo.start()
+ }
+
+ fun hideFromActivity() {
+ fakeBroadcastDispatcher.sendIntentToMatchingReceiversOnly(
+ context,
+ Intent(Intent.ACTION_DISMISS_KEYBOARD_SHORTCUTS)
+ )
+ }
+
+ fun showFromActivity() {
+ fakeBroadcastDispatcher.sendIntentToMatchingReceiversOnly(
+ context,
+ Intent(Intent.ACTION_SHOW_KEYBOARD_SHORTCUTS)
+ )
+ }
+
+ fun toggle(deviceId: Int) {
+ fakeCommandQueue.doForEachCallback { it.toggleKeyboardShortcutsMenu(deviceId) }
+ }
+
+ fun hideForSystem() {
+ fakeCommandQueue.doForEachCallback { it.dismissKeyboardShortcutsMenu() }
+ }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
index 1e305d6..96a4049 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
@@ -19,6 +19,7 @@
import android.graphics.Point
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.shared.model.BiometricUnlockMode
import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
import com.android.systemui.keyguard.shared.model.BiometricUnlockSource
import com.android.systemui.keyguard.shared.model.DismissAction
@@ -101,7 +102,8 @@
private val _isKeyguardGoingAway = MutableStateFlow(false)
override val isKeyguardGoingAway: Flow<Boolean> = _isKeyguardGoingAway
- private val _biometricUnlockState = MutableStateFlow(BiometricUnlockModel.NONE)
+ private val _biometricUnlockState =
+ MutableStateFlow(BiometricUnlockModel(BiometricUnlockMode.NONE, null))
override val biometricUnlockState: Flow<BiometricUnlockModel> = _biometricUnlockState
private val _fingerprintSensorLocation = MutableStateFlow<Point?>(null)
@@ -110,9 +112,6 @@
private val _faceSensorLocation = MutableStateFlow<Point?>(null)
override val faceSensorLocation: Flow<Point?> = _faceSensorLocation
- private val _biometricUnlockSource = MutableStateFlow<BiometricUnlockSource?>(null)
- override val biometricUnlockSource: Flow<BiometricUnlockSource?> = _biometricUnlockSource
-
private val _isQuickSettingsVisible = MutableStateFlow(false)
override val isQuickSettingsVisible: Flow<Boolean> = _isQuickSettingsVisible.asStateFlow()
@@ -213,12 +212,19 @@
_dozeAmount.value = dozeAmount
}
- override fun setBiometricUnlockState(value: BiometricUnlockModel) {
- _biometricUnlockState.tryEmit(value)
+ override fun setBiometricUnlockState(
+ mode: BiometricUnlockMode,
+ source: BiometricUnlockSource?
+ ) {
+ _biometricUnlockState.tryEmit(BiometricUnlockModel(mode, source))
+ }
+
+ fun setBiometricUnlockState(mode: BiometricUnlockMode) {
+ setBiometricUnlockState(mode, BiometricUnlockSource.FINGERPRINT_SENSOR)
}
fun setBiometricUnlockSource(source: BiometricUnlockSource?) {
- _biometricUnlockSource.tryEmit(source)
+ setBiometricUnlockState(BiometricUnlockMode.NONE, source)
}
fun setFaceSensorLocation(location: Point?) {
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardSmartspaceRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardSmartspaceRepository.kt
new file mode 100644
index 0000000..42cb150
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardSmartspaceRepository.kt
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.data.repository
+
+import android.view.View.GONE
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+
+class FakeKeyguardSmartspaceRepository : KeyguardSmartspaceRepository {
+
+ private val _bcSmartspaceVisibility = MutableStateFlow(GONE)
+ override val bcSmartspaceVisibility: StateFlow<Int> = _bcSmartspaceVisibility
+ private val _isWeatherEnabled = MutableStateFlow(true)
+ override val isWeatherEnabled: StateFlow<Boolean> = _isWeatherEnabled
+
+ override fun setBcSmartspaceVisibility(visibility: Int) {
+ _bcSmartspaceVisibility.value = visibility
+ }
+
+ fun setIsWeatherEnabled(isEnabled: Boolean) {
+ _isWeatherEnabled.value = isEnabled
+ }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardTransitionRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardTransitionRepository.kt
index a242368..2fe7438 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardTransitionRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardTransitionRepository.kt
@@ -40,12 +40,21 @@
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
-/** Fake implementation of [KeyguardTransitionRepository] */
+/**
+ * Fake implementation of [KeyguardTransitionRepository].
+ *
+ * By default, will be seeded with a transition from OFF -> LOCKSCREEN, which is the most common
+ * case. If the lockscreen is disabled, or we're in setup wizard, the repository will initialize
+ * with OFF -> GONE. Construct with initInLockscreen = false if your test requires this behavior.
+ */
@SysUISingleton
-class FakeKeyguardTransitionRepository @Inject constructor() : KeyguardTransitionRepository {
+class FakeKeyguardTransitionRepository(
+ private val initInLockscreen: Boolean = true,
+) : KeyguardTransitionRepository {
private val _transitions =
MutableSharedFlow<TransitionStep>(replay = 3, onBufferOverflow = BufferOverflow.DROP_OLDEST)
override val transitions: SharedFlow<TransitionStep> = _transitions
+ @Inject constructor() : this(initInLockscreen = true)
private val _currentTransitionInfo: MutableStateFlow<TransitionInfo> =
MutableStateFlow(
@@ -59,8 +68,21 @@
override var currentTransitionInfoInternal = _currentTransitionInfo.asStateFlow()
init {
- // Seed the fake repository with the same initial steps the actual repository uses.
- KeyguardTransitionRepositoryImpl.initialTransitionSteps.forEach { _transitions.tryEmit(it) }
+ // Seed with a FINISHED transition in OFF, same as the real repository.
+ _transitions.tryEmit(
+ TransitionStep(
+ KeyguardState.OFF,
+ KeyguardState.OFF,
+ 1f,
+ TransitionState.FINISHED,
+ )
+ )
+
+ if (initInLockscreen) {
+ tryEmitInitialStepsFromOff(KeyguardState.LOCKSCREEN)
+ } else {
+ tryEmitInitialStepsFromOff(KeyguardState.OFF)
+ }
}
/**
@@ -223,6 +245,32 @@
return if (info.animator == null) UUID.randomUUID() else null
}
+ override suspend fun emitInitialStepsFromOff(to: KeyguardState) {
+ tryEmitInitialStepsFromOff(to)
+ }
+
+ private fun tryEmitInitialStepsFromOff(to: KeyguardState) {
+ _transitions.tryEmit(
+ TransitionStep(
+ KeyguardState.OFF,
+ to,
+ 0f,
+ TransitionState.STARTED,
+ ownerName = "KeyguardTransitionRepository(boot)",
+ )
+ )
+
+ _transitions.tryEmit(
+ TransitionStep(
+ KeyguardState.OFF,
+ to,
+ 1f,
+ TransitionState.FINISHED,
+ ownerName = "KeyguardTransitionRepository(boot)",
+ ),
+ )
+ }
+
override fun updateTransition(
transitionId: UUID,
@FloatRange(from = 0.0, to = 1.0) value: Float,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/KeyguardSmartspaceRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/KeyguardSmartspaceRepositoryKosmos.kt
index dc7103f..2949452 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/KeyguardSmartspaceRepositoryKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/KeyguardSmartspaceRepositoryKosmos.kt
@@ -18,4 +18,4 @@
import com.android.systemui.kosmos.Kosmos
-val Kosmos.keyguardSmartspaceRepository by Kosmos.Fixture { KeyguardSmartspaceRepository() }
+val Kosmos.keyguardSmartspaceRepository by Kosmos.Fixture { FakeKeyguardSmartspaceRepository() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt
index 2e751cc..02842cc 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt
@@ -53,6 +53,7 @@
shadeRepository: FakeShadeRepository = FakeShadeRepository(),
sceneInteractor: SceneInteractor = mock(),
fromGoneTransitionInteractor: FromGoneTransitionInteractor = mock(),
+ fromLockscreenTransitionInteractor: FromLockscreenTransitionInteractor = mock(),
sharedNotificationContainerInteractor: SharedNotificationContainerInteractor? = null,
powerInteractor: PowerInteractor = PowerInteractorFactory.create().powerInteractor,
testScope: CoroutineScope = TestScope(),
@@ -98,6 +99,7 @@
keyguardTransitionInteractor = keyguardTransitionInteractor,
sceneInteractorProvider = { sceneInteractor },
fromGoneTransitionInteractor = { fromGoneTransitionInteractor },
+ fromLockscreenTransitionInteractor = { fromLockscreenTransitionInteractor },
sharedNotificationContainerInteractor = { sncInteractor },
applicationScope = testScope,
),
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorKosmos.kt
index 9426718..81d8f0b 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorKosmos.kt
@@ -18,20 +18,20 @@
import com.android.systemui.bouncer.data.repository.keyguardBouncerRepository
import com.android.systemui.common.ui.domain.interactor.configurationInteractor
+import com.android.systemui.keyguard.data.repository.fakeCommandQueue
import com.android.systemui.keyguard.data.repository.keyguardRepository
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.testScope
import com.android.systemui.power.domain.interactor.powerInteractor
import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.shade.data.repository.shadeRepository
-import com.android.systemui.statusbar.commandQueue
import com.android.systemui.statusbar.notification.stack.domain.interactor.sharedNotificationContainerInteractor
val Kosmos.keyguardInteractor: KeyguardInteractor by
Kosmos.Fixture {
KeyguardInteractor(
repository = keyguardRepository,
- commandQueue = commandQueue,
+ commandQueue = fakeCommandQueue,
powerInteractor = powerInteractor,
bouncerRepository = keyguardBouncerRepository,
configurationInteractor = configurationInteractor,
@@ -39,6 +39,7 @@
keyguardTransitionInteractor = keyguardTransitionInteractor,
sceneInteractorProvider = { sceneInteractor },
fromGoneTransitionInteractor = { fromGoneTransitionInteractor },
+ fromLockscreenTransitionInteractor = { fromLockscreenTransitionInteractor },
sharedNotificationContainerInteractor = { sharedNotificationContainerInteractor },
applicationScope = testScope.backgroundScope,
)
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionBootInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionBootInteractorKosmos.kt
new file mode 100644
index 0000000..7d8d33f
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionBootInteractorKosmos.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.domain.interactor
+
+import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
+import com.android.systemui.keyguard.data.repository.keyguardTransitionRepository
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.statusbar.policy.domain.interactor.deviceProvisioningInteractor
+
+val Kosmos.keyguardTransitionBootInteractor: KeyguardTransitionBootInteractor by
+ Kosmos.Fixture {
+ KeyguardTransitionBootInteractor(
+ scope = applicationCoroutineScope,
+ deviceEntryInteractor = deviceEntryInteractor,
+ deviceProvisioningInteractor = deviceProvisioningInteractor,
+ keyguardTransitionInteractor = keyguardTransitionInteractor,
+ repository = keyguardTransitionRepository,
+ )
+ }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/GridLayoutTypeInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/GridLayoutTypeInteractorKosmos.kt
index e44fa07..c951642 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/GridLayoutTypeInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/GridLayoutTypeInteractorKosmos.kt
@@ -18,6 +18,12 @@
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.qs.panels.data.repository.gridLayoutTypeRepository
+import com.android.systemui.qs.panels.shared.model.GridLayoutType
+import com.android.systemui.qs.panels.shared.model.InfiniteGridLayoutType
+import com.android.systemui.qs.panels.ui.compose.GridLayout
val Kosmos.gridLayoutTypeInteractor by
Kosmos.Fixture { GridLayoutTypeInteractor(gridLayoutTypeRepository) }
+
+val Kosmos.gridLayoutMap: Map<GridLayoutType, GridLayout> by
+ Kosmos.Fixture { mapOf(Pair(InfiniteGridLayoutType, infiniteGridLayout)) }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/shared/model/GridLayoutTypeKey.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/InfiniteGridLayoutKosmos.kt
similarity index 63%
copy from packages/SystemUI/src/com/android/systemui/qs/panels/shared/model/GridLayoutTypeKey.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/InfiniteGridLayoutKosmos.kt
index 0dbaaba..1893c30 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/shared/model/GridLayoutTypeKey.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/InfiniteGridLayoutKosmos.kt
@@ -14,15 +14,9 @@
* limitations under the License.
*/
-package com.android.systemui.qs.panels.shared.model
+package com.android.systemui.qs.panels.domain.interactor
-import dagger.MapKey
-import kotlin.reflect.KClass
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.qs.panels.ui.compose.InfiniteGridLayout
-/**
- * Dagger map key to associate a [GridLayoutType] with its
- * [com.android.systemui.qs.panels.ui.compose.GridLayout].
- */
-@Retention(AnnotationRetention.RUNTIME)
-@MapKey
-annotation class GridLayoutTypeKey(val value: KClass<out GridLayoutType>)
+val Kosmos.infiniteGridLayout by Kosmos.Fixture { InfiniteGridLayout(iconTilesInteractor) }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/ui/viewmodel/TileGridViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/ui/viewmodel/TileGridViewModelKosmos.kt
index 9851f04..5fd8762 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/ui/viewmodel/TileGridViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/ui/viewmodel/TileGridViewModelKosmos.kt
@@ -17,9 +17,10 @@
package com.android.systemui.qs.panels.ui.viewmodel
import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.qs.panels.domain.interactor.gridLayoutMap
import com.android.systemui.qs.panels.domain.interactor.gridLayoutTypeInteractor
import com.android.systemui.qs.panels.domain.interactor.iconTilesInteractor
-import com.android.systemui.qs.panels.shared.model.InfiniteGridLayoutType
import com.android.systemui.qs.panels.ui.compose.InfiniteGridLayout
import com.android.systemui.qs.pipeline.domain.interactor.currentTilesInteractor
@@ -27,8 +28,9 @@
Kosmos.Fixture {
TileGridViewModel(
gridLayoutTypeInteractor,
- mapOf(Pair(InfiniteGridLayoutType::class.java, InfiniteGridLayout())),
+ gridLayoutMap,
currentTilesInteractor,
- iconTilesInteractor
+ InfiniteGridLayout(iconTilesInteractor),
+ applicationCoroutineScope,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/base/actions/FakeQSTileIntentUserInputHandler.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/base/actions/FakeQSTileIntentUserInputHandler.kt
index 0307c41..c4bf8ff 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/base/actions/FakeQSTileIntentUserInputHandler.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/base/actions/FakeQSTileIntentUserInputHandler.kt
@@ -18,7 +18,7 @@
import android.app.PendingIntent
import android.content.Intent
-import android.view.View
+import com.android.systemui.animation.Expandable
/**
* Fake implementation of [QSTileIntentUserInputHandler] interface. Consider using this alongside
@@ -31,22 +31,24 @@
private val mutableInputs = mutableListOf<Input>()
- override fun handle(view: View?, intent: Intent) {
- mutableInputs.add(Input.Intent(view, intent))
+ override fun handle(expandable: Expandable?, intent: Intent) {
+ mutableInputs.add(Input.Intent(expandable, intent))
}
override fun handle(
- view: View?,
+ expandable: Expandable?,
pendingIntent: PendingIntent,
requestLaunchingDefaultActivity: Boolean
) {
- mutableInputs.add(Input.PendingIntent(view, pendingIntent, requestLaunchingDefaultActivity))
+ mutableInputs.add(
+ Input.PendingIntent(expandable, pendingIntent, requestLaunchingDefaultActivity)
+ )
}
sealed interface Input {
- data class Intent(val view: View?, val intent: android.content.Intent) : Input
+ data class Intent(val expandable: Expandable?, val intent: android.content.Intent) : Input
data class PendingIntent(
- val view: View?,
+ val expandable: Expandable?,
val pendingIntent: android.app.PendingIntent,
val requestLaunchingDefaultActivity: Boolean
) : Input
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/base/interactor/QSTileInputTestKtx.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/base/interactor/QSTileInputTestKtx.kt
index 832b07a..9cb76bb 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/base/interactor/QSTileInputTestKtx.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/base/interactor/QSTileInputTestKtx.kt
@@ -17,7 +17,7 @@
package com.android.systemui.qs.tiles.base.interactor
import android.os.UserHandle
-import android.view.View
+import com.android.systemui.animation.Expandable
import com.android.systemui.qs.tiles.viewmodel.QSTileUserAction
object QSTileInputTestKtx {
@@ -25,12 +25,12 @@
fun <T> click(
data: T,
user: UserHandle = UserHandle.CURRENT,
- view: View? = null,
- ): QSTileInput<T> = QSTileInput(user, QSTileUserAction.Click(view), data)
+ expandable: Expandable? = null,
+ ): QSTileInput<T> = QSTileInput(user, QSTileUserAction.Click(expandable), data)
fun <T> longClick(
data: T,
user: UserHandle = UserHandle.CURRENT,
- view: View? = null,
- ): QSTileInput<T> = QSTileInput(user, QSTileUserAction.LongClick(view), data)
+ expandable: Expandable? = null,
+ ): QSTileInput<T> = QSTileInput(user, QSTileUserAction.LongClick(expandable), data)
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/shared/model/GridLayoutTypeKey.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/impl/onehanded/OneHandedModeTileKosmos.kt
similarity index 63%
copy from packages/SystemUI/src/com/android/systemui/qs/panels/shared/model/GridLayoutTypeKey.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/impl/onehanded/OneHandedModeTileKosmos.kt
index 0dbaaba..d9c0361 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/shared/model/GridLayoutTypeKey.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/impl/onehanded/OneHandedModeTileKosmos.kt
@@ -14,15 +14,11 @@
* limitations under the License.
*/
-package com.android.systemui.qs.panels.shared.model
+package com.android.systemui.qs.tiles.impl.onehanded
-import dagger.MapKey
-import kotlin.reflect.KClass
+import com.android.systemui.accessibility.qs.QSAccessibilityModule
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.qs.qsEventLogger
-/**
- * Dagger map key to associate a [GridLayoutType] with its
- * [com.android.systemui.qs.panels.ui.compose.GridLayout].
- */
-@Retention(AnnotationRetention.RUNTIME)
-@MapKey
-annotation class GridLayoutTypeKey(val value: KClass<out GridLayoutType>)
+val Kosmos.qsOneHandedModeTileConfig by
+ Kosmos.Fixture { QSAccessibilityModule.provideOneHandedTileConfig(qsEventLogger) }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/adapter/FakeQSSceneAdapter.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/adapter/FakeQSSceneAdapter.kt
index a654d6f..e0f60e9 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/adapter/FakeQSSceneAdapter.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/adapter/FakeQSSceneAdapter.kt
@@ -21,7 +21,6 @@
import com.android.systemui.settings.brightness.MirrorController
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.filterNotNull
@@ -30,8 +29,16 @@
override val qqsHeight: Int = 0,
override val qsHeight: Int = 0,
) : QSSceneAdapter {
+ private val _customizerState = MutableStateFlow<CustomizerState>(CustomizerState.Hidden)
+
+ private val _customizerShowing = MutableStateFlow(false)
+ override val isCustomizerShowing = _customizerShowing.asStateFlow()
+
private val _customizing = MutableStateFlow(false)
- override val isCustomizing: StateFlow<Boolean> = _customizing.asStateFlow()
+ override val isCustomizing = _customizing.asStateFlow()
+
+ private val _animationDuration = MutableStateFlow(0)
+ override val customizerAnimationDuration = _animationDuration.asStateFlow()
private val _view = MutableStateFlow<View?>(null)
override val qsView: Flow<View> = _view.filterNotNull()
@@ -58,7 +65,7 @@
}
fun setCustomizing(value: Boolean) {
- _customizing.value = value
+ updateCustomizerFlows(if (value) CustomizerState.Showing else CustomizerState.Hidden)
}
override suspend fun applyBottomNavBarPadding(padding: Int) {
@@ -66,10 +73,18 @@
}
override fun requestCloseCustomizer() {
- _customizing.value = false
+ updateCustomizerFlows(CustomizerState.Hidden)
}
override fun setBrightnessMirrorController(mirrorController: MirrorController?) {
brightnessMirrorController = mirrorController
}
+
+ private fun updateCustomizerFlows(customizerState: CustomizerState) {
+ _customizerState.value = customizerState
+ _customizing.value = customizerState.isCustomizing
+ _customizerShowing.value = customizerState.isShowing
+ _animationDuration.value =
+ (customizerState as? CustomizerState.Animating)?.animationDuration?.toInt() ?: 0
+ }
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/SceneContainerStartableKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/SceneContainerStartableKosmos.kt
index ebe591b..d82286f 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/SceneContainerStartableKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/SceneContainerStartableKosmos.kt
@@ -32,6 +32,7 @@
import com.android.systemui.model.sysUiState
import com.android.systemui.power.domain.interactor.powerInteractor
import com.android.systemui.scene.domain.startable.SceneContainerStartable
+import com.android.systemui.scene.session.shared.shadeSessionStorage
import com.android.systemui.scene.shared.logger.sceneLogger
import com.android.systemui.settings.displayTracker
import com.android.systemui.shade.domain.interactor.shadeInteractor
@@ -65,5 +66,6 @@
shadeInteractor = shadeInteractor,
uiEventLogger = uiEventLogger,
sceneBackInteractor = sceneBackInteractor,
+ shadeSessionStorage = shadeSessionStorage,
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/shared/model/GridLayoutTypeKey.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/session/shared/SessionStorageKosmos.kt
similarity index 63%
copy from packages/SystemUI/src/com/android/systemui/qs/panels/shared/model/GridLayoutTypeKey.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/scene/session/shared/SessionStorageKosmos.kt
index 0dbaaba..0bee937 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/shared/model/GridLayoutTypeKey.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/session/shared/SessionStorageKosmos.kt
@@ -14,15 +14,9 @@
* limitations under the License.
*/
-package com.android.systemui.qs.panels.shared.model
+package com.android.systemui.scene.session.shared
-import dagger.MapKey
-import kotlin.reflect.KClass
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
-/**
- * Dagger map key to associate a [GridLayoutType] with its
- * [com.android.systemui.qs.panels.ui.compose.GridLayout].
- */
-@Retention(AnnotationRetention.RUNTIME)
-@MapKey
-annotation class GridLayoutTypeKey(val value: KClass<out GridLayoutType>)
+var Kosmos.shadeSessionStorage by Fixture { SessionStorage() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/shared/model/FakeSceneDataSource.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/shared/model/FakeSceneDataSource.kt
index 59a01cb..957a60f 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/shared/model/FakeSceneDataSource.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/shared/model/FakeSceneDataSource.kt
@@ -42,6 +42,10 @@
}
}
+ override fun snapToScene(toScene: SceneKey) {
+ changeScene(toScene)
+ }
+
/**
* Pauses scene changes.
*
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeTestUtil.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeTestUtil.kt
index 0101961..38ede44 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeTestUtil.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeTestUtil.kt
@@ -23,6 +23,7 @@
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.shade.data.repository.FakeShadeRepository
import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
import org.junit.Assert
@@ -58,11 +59,23 @@
delegate.setLockscreenShadeExpansion(lockscreenShadeExpansion)
}
- /** Sets whether the user is moving the shade with touch input. */
+ /** Sets whether the user is moving the shade with touch input on Lockscreen. */
fun setLockscreenShadeTracking(lockscreenShadeTracking: Boolean) {
delegate.assertFlagValid()
delegate.setLockscreenShadeTracking(lockscreenShadeTracking)
}
+
+ /** Sets whether the user is moving the shade with touch input. */
+ fun setTracking(tracking: Boolean) {
+ delegate.assertFlagValid()
+ delegate.setTracking(tracking)
+ }
+
+ /** Sets the shade to half collapsed with no touch input. */
+ fun programmaticCollapseShade() {
+ delegate.assertFlagValid()
+ delegate.programmaticCollapseShade()
+ }
}
/** Sets up shade state for tests for a specific value of the scene container flag. */
@@ -79,11 +92,17 @@
/** Sets whether the user is moving the shade with touch input. */
fun setLockscreenShadeTracking(lockscreenShadeTracking: Boolean)
+ /** Sets whether the user is moving the shade with touch input. */
+ fun setTracking(tracking: Boolean)
+
/** Sets shade expansion to a value between 0-1. */
fun setShadeExpansion(shadeExpansion: Float)
/** Sets QS expansion to a value between 0-1. */
fun setQsExpansion(qsExpansion: Float)
+
+ /** Sets the shade to half collapsed with no touch input. */
+ fun programmaticCollapseShade()
}
/** Sets up shade state for tests when the scene container flag is disabled. */
@@ -103,6 +122,10 @@
shadeRepository.setLegacyLockscreenShadeTracking(lockscreenShadeTracking)
}
+ override fun setTracking(tracking: Boolean) {
+ shadeRepository.setLegacyShadeTracking(tracking)
+ }
+
override fun assertFlagValid() {
Assert.assertFalse(SceneContainerFlag.isEnabled)
}
@@ -118,6 +141,11 @@
shadeRepository.setQsExpansion(qsExpansion)
testScope.runCurrent()
}
+
+ override fun programmaticCollapseShade() {
+ shadeRepository.setLegacyShadeExpansion(.5f)
+ testScope.runCurrent()
+ }
}
/** Sets up shade state for tests when the scene container flag is enabled. */
@@ -126,14 +154,16 @@
val isUserInputOngoing = MutableStateFlow(true)
override fun setShadeAndQsExpansion(shadeExpansion: Float, qsExpansion: Float) {
- if (shadeExpansion == 0f) {
- setTransitionProgress(Scenes.Lockscreen, Scenes.QuickSettings, qsExpansion)
- } else if (qsExpansion == 0f) {
- setTransitionProgress(Scenes.Lockscreen, Scenes.Shade, shadeExpansion)
- } else if (shadeExpansion == 1f) {
+ if (shadeExpansion == 1f) {
setIdleScene(Scenes.Shade)
} else if (qsExpansion == 1f) {
setIdleScene(Scenes.QuickSettings)
+ } else if (shadeExpansion == 0f && qsExpansion == 0f) {
+ setIdleScene(Scenes.Lockscreen)
+ } else if (shadeExpansion == 0f) {
+ setTransitionProgress(Scenes.Lockscreen, Scenes.QuickSettings, qsExpansion)
+ } else if (qsExpansion == 0f) {
+ setTransitionProgress(Scenes.Lockscreen, Scenes.Shade, shadeExpansion)
} else {
setTransitionProgress(Scenes.Shade, Scenes.QuickSettings, qsExpansion)
}
@@ -149,6 +179,10 @@
setShadeAndQsExpansion(0f, qsExpansion)
}
+ override fun programmaticCollapseShade() {
+ setTransitionProgress(Scenes.Shade, Scenes.Lockscreen, .5f, false)
+ }
+
override fun setLockscreenShadeExpansion(lockscreenShadeExpansion: Float) {
if (lockscreenShadeExpansion == 0f) {
setIdleScene(Scenes.Lockscreen)
@@ -160,7 +194,11 @@
}
override fun setLockscreenShadeTracking(lockscreenShadeTracking: Boolean) {
- isUserInputOngoing.value = lockscreenShadeTracking
+ setTracking(lockscreenShadeTracking)
+ }
+
+ override fun setTracking(tracking: Boolean) {
+ isUserInputOngoing.value = tracking
}
private fun setIdleScene(scene: SceneKey) {
@@ -171,15 +209,21 @@
testScope.runCurrent()
}
- private fun setTransitionProgress(from: SceneKey, to: SceneKey, progress: Float) {
+ private fun setTransitionProgress(
+ from: SceneKey,
+ to: SceneKey,
+ progress: Float,
+ isInitiatedByUserInput: Boolean = true
+ ) {
sceneInteractor.changeScene(from, "test")
val transitionState =
MutableStateFlow<ObservableTransitionState>(
ObservableTransitionState.Transition(
fromScene = from,
toScene = to,
+ currentScene = flowOf(to),
progress = MutableStateFlow(progress),
- isInitiatedByUserInput = true,
+ isInitiatedByUserInput = isInitiatedByUserInput,
isUserInputOngoing = isUserInputOngoing,
)
)
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/NotificationsShadeSceneViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/NotificationsShadeSceneViewModelKosmos.kt
new file mode 100644
index 0000000..872eba06
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/NotificationsShadeSceneViewModelKosmos.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shade.ui.viewmodel
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.notifications.ui.viewmodel.NotificationsShadeSceneViewModel
+
+val Kosmos.notificationsShadeSceneViewModel: NotificationsShadeSceneViewModel by
+ Kosmos.Fixture {
+ NotificationsShadeSceneViewModel(
+ applicationScope = applicationCoroutineScope,
+ overlayShadeViewModel = overlayShadeViewModel,
+ )
+ }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/OverlayShadeViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/OverlayShadeViewModelKosmos.kt
new file mode 100644
index 0000000..45ec032
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/OverlayShadeViewModelKosmos.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.shade.ui.viewmodel
+
+import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.scene.domain.interactor.sceneInteractor
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+
+val Kosmos.overlayShadeViewModel: OverlayShadeViewModel by
+ Kosmos.Fixture {
+ OverlayShadeViewModel(
+ applicationScope = applicationCoroutineScope,
+ sceneInteractor = sceneInteractor,
+ deviceEntryInteractor = deviceEntryInteractor,
+ )
+ }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/QuickSettingsShadeSceneViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/QuickSettingsShadeSceneViewModelKosmos.kt
new file mode 100644
index 0000000..8c5ff1d
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/QuickSettingsShadeSceneViewModelKosmos.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shade.ui.viewmodel
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.qs.ui.viewmodel.QuickSettingsShadeSceneViewModel
+
+val Kosmos.quickSettingsShadeSceneViewModel: QuickSettingsShadeSceneViewModel by
+ Kosmos.Fixture {
+ QuickSettingsShadeSceneViewModel(
+ applicationScope = applicationCoroutineScope,
+ overlayShadeViewModel = overlayShadeViewModel,
+ )
+ }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/user/data/repository/FakeUserRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/user/data/repository/FakeUserRepository.kt
index 3e9ae4d..1f2ecb7 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/user/data/repository/FakeUserRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/user/data/repository/FakeUserRepository.kt
@@ -37,7 +37,7 @@
class FakeUserRepository @Inject constructor() : UserRepository {
companion object {
// User id to represent a non system (human) user id. We presume this is the main user.
- private const val MAIN_USER_ID = 10
+ const val MAIN_USER_ID = 10
private const val DEFAULT_SELECTED_USER = 0
private val DEFAULT_SELECTED_USER_INFO =
@@ -84,6 +84,10 @@
override var isRefreshUsersPaused: Boolean = false
+ override suspend fun getMainUserId(): Int? {
+ return MAIN_USER_ID
+ }
+
var refreshUsersCallCount: Int = 0
private set
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/util/mockito/KotlinMockitoHelpers.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/util/mockito/KotlinMockitoHelpers.kt
index efccafc..295e150 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/util/mockito/KotlinMockitoHelpers.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/util/mockito/KotlinMockitoHelpers.kt
@@ -22,6 +22,7 @@
* be null"). To fix this, we can use methods that modify the return type to be nullable. This
* causes Kotlin to skip the null checks.
*/
+import kotlin.DeprecationLevel.WARNING
import org.mockito.ArgumentCaptor
import org.mockito.ArgumentMatcher
import org.mockito.MockSettings
@@ -37,6 +38,11 @@
*
* Generic T is nullable because implicitly bounded by Any?.
*/
+@Deprecated(
+ "Replace with mockito-kotlin. See http://go/mockito-kotlin",
+ ReplaceWith(expression = "eq", imports = ["org.mockito.kotlin.eq"]),
+ level = WARNING
+)
fun <T> eq(obj: T): T = Mockito.eq<T>(obj) ?: obj
/**
@@ -45,8 +51,18 @@
*
* Generic T is nullable because implicitly bounded by Any?.
*/
+@Deprecated(
+ "Replace with mockito-kotlin. See http://go/mockito-kotlin",
+ ReplaceWith(expression = "any(type)", imports = ["org.mockito.kotlin.any"]),
+ level = WARNING
+)
fun <T> any(type: Class<T>): T = Mockito.any<T>(type)
+@Deprecated(
+ "Replace with mockito-kotlin. See http://go/mockito-kotlin",
+ ReplaceWith(expression = "any()", imports = ["org.mockito.kotlin.any"]),
+ level = WARNING
+)
inline fun <reified T> any(): T = any(T::class.java)
/**
@@ -55,9 +71,23 @@
*
* Generic T is nullable because implicitly bounded by Any?.
*/
+@Deprecated(
+ "Replace with mockito-kotlin. See http://go/mockito-kotlin",
+ ReplaceWith(expression = "argThat(matcher)", imports = ["org.mockito.kotlin.argThat"]),
+ level = WARNING
+)
fun <T> argThat(matcher: ArgumentMatcher<T>): T = Mockito.argThat(matcher)
-/** Kotlin type-inferred version of Mockito.nullable() */
+/**
+ * Kotlin type-inferred version of Mockito.nullable()
+ *
+ * @see org.mockito.kotlin.anyOrNull
+ */
+@Deprecated(
+ "Replace with mockito-kotlin. See http://go/mockito-kotlin",
+ ReplaceWith(expression = "anyOrNull()", imports = ["org.mockito.kotlin.anyOrNull"]),
+ level = WARNING
+)
inline fun <reified T> nullable(): T? = Mockito.nullable(T::class.java)
/**
@@ -65,14 +95,28 @@
* null is returned.
*
* Generic T is nullable because implicitly bounded by Any?.
+ *
+ * @see org.mockito.kotlin.capture
*/
+@Deprecated(
+ "Replace with mockito-kotlin. See http://go/mockito-kotlin",
+ ReplaceWith(expression = "capture(argumentCaptor)", imports = ["org.mockito.kotlin.capture"]),
+ level = WARNING
+)
fun <T> capture(argumentCaptor: ArgumentCaptor<T>): T = argumentCaptor.capture()
/**
* Helper function for creating an argumentCaptor in kotlin.
*
* Generic T is nullable because implicitly bounded by Any?.
+ *
+ * @see org.mockito.kotlin.argumentCaptor
*/
+@Deprecated(
+ "Replace with mockito-kotlin. See http://go/mockito-kotlin",
+ ReplaceWith(expression = "argumentCaptor()", imports = ["org.mockito.kotlin.argumentCaptor"]),
+ level = WARNING
+)
inline fun <reified T : Any> argumentCaptor(): ArgumentCaptor<T> =
ArgumentCaptor.forClass(T::class.java)
@@ -81,18 +125,55 @@
*
* Generic T is nullable because implicitly bounded by Any?.
*
+ * Updated kotlin-mockito usage:
+ * ```
+ * val value: Widget = mock<> {
+ * on { status } doReturn "OK"
+ * on { buttonPress } doNothing
+ * on { destroy } doAnswer error("Boom!")
+ * }
+ * ```
+ *
+ * __Deprecation note__
+ *
+ * Automatic replacement is not possible due to a change in lambda receiver type to KStubbing<T>
+ *
* @param apply builder function to simplify stub configuration by improving type inference.
+ * @see org.mockito.kotlin.mock
+ * @see org.mockito.kotlin.KStubbing.on
*/
+@Suppress("DeprecatedCallableAddReplaceWith")
+@Deprecated("Replace with mockito-kotlin. See http://go/mockito-kotlin", level = WARNING)
inline fun <reified T : Any> mock(settings: MockSettings? = null, apply: T.() -> Unit = {}): T =
Mockito.mock(T::class.java, settings ?: withSettings()).apply(apply)
/**
* Helper function for stubbing methods without the need to use backticks.
*
- * @see Mockito.when
+ * Avoid. It is preferable to provide stubbing at creation time using the [mock] lambda argument.
+ *
+ * @see org.mockito.kotlin.whenever
*/
+@Deprecated(
+ "Replace with mockito-kotlin. See http://go/mockito-kotlin",
+ ReplaceWith(expression = "whenever(methodCall)", imports = ["org.mockito.kotlin.whenever"]),
+ level = WARNING
+)
fun <T> whenever(methodCall: T): OngoingStubbing<T> = `when`(methodCall)
+/**
+ * __Deprecation note__
+ *
+ * Replace with `KStubbing<T>.on` within [org.mockito.kotlin.mock] { stubbing }
+ *
+ * @see org.mockito.kotlin.mock
+ * @see org.mockito.kotlin.KStubbing.on
+ */
+@Deprecated(
+ "Replace with mockito-kotlin. See http://go/mockito-kotlin",
+ ReplaceWith(expression = "whenever(mock)", imports = ["org.mockito.kotlin.whenever"]),
+ level = WARNING
+)
fun <T> Stubber.whenever(mock: T): T = `when`(mock)
/**
@@ -101,6 +182,7 @@
*
* java.lang.NullPointerException: capture() must not be null
*/
+@Deprecated("Replace with mockito-kotlin. See http://go/mockito-kotlin", level = WARNING)
class KotlinArgumentCaptor<T> constructor(clazz: Class<T>) {
private val wrapped: ArgumentCaptor<T> = ArgumentCaptor.forClass(clazz)
fun capture(): T = wrapped.capture()
@@ -114,7 +196,14 @@
* Helper function for creating an argumentCaptor in kotlin.
*
* Generic T is nullable because implicitly bounded by Any?.
+ *
+ * @see org.mockito.kotlin.argumentCaptor
*/
+@Deprecated(
+ "Replace with mockito-kotlin. See http://go/mockito-kotlin",
+ ReplaceWith(expression = "argumentCaptor()", imports = ["org.mockito.kotlin.argumentCaptor"]),
+ level = WARNING
+)
inline fun <reified T : Any> kotlinArgumentCaptor(): KotlinArgumentCaptor<T> =
KotlinArgumentCaptor(T::class.java)
@@ -130,6 +219,7 @@
*
* NOTE: this uses the KotlinArgumentCaptor to avoid the NullPointerException.
*/
+@Deprecated("Replace with mockito-kotlin", level = WARNING)
inline fun <reified T : Any> withArgCaptor(block: KotlinArgumentCaptor<T>.() -> Unit): T =
kotlinArgumentCaptor<T>().apply { block() }.value
@@ -142,6 +232,10 @@
* becomes:
*
* val capturedList = captureMany<Foo> { verify(...).someMethod(capture()) }
+ *
+ * @see org.mockito.kotlin.verify
*/
+@Suppress("DeprecatedCallableAddReplaceWith")
+@Deprecated("Replace with mockito-kotlin. See http://go/mockito-kotlin", level = WARNING)
inline fun <reified T : Any> captureMany(block: KotlinArgumentCaptor<T>.() -> Unit): List<T> =
kotlinArgumentCaptor<T>().apply { block() }.allValues
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeBatteryController.java b/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeBatteryController.java
index d798b3b..0364e05 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeBatteryController.java
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeBatteryController.java
@@ -16,8 +16,8 @@
import android.os.Bundle;
import android.testing.LeakCheck;
-import android.view.View;
+import com.android.systemui.animation.Expandable;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
@@ -61,7 +61,7 @@
* Note: this method ignores the View argument
*/
@Override
- public void setPowerSaveMode(boolean powerSave, View view) {
+ public void setPowerSaveMode(boolean powerSave, Expandable expandable) {
setPowerSaveMode(powerSave);
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/MediaControllerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/MediaControllerKosmos.kt
index 5db1724..546a797 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/MediaControllerKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/MediaControllerKosmos.kt
@@ -19,8 +19,10 @@
import android.content.packageManager
import android.content.pm.ApplicationInfo
import android.media.AudioAttributes
+import android.media.VolumeProvider
import android.media.session.MediaController
import android.media.session.MediaSession
+import android.media.session.PlaybackState
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.eq
@@ -28,6 +30,18 @@
import com.android.systemui.util.mockito.whenever
private const val LOCAL_PACKAGE = "local.test.pkg"
+var Kosmos.localPlaybackInfo by
+ Kosmos.Fixture {
+ MediaController.PlaybackInfo(
+ MediaController.PlaybackInfo.PLAYBACK_TYPE_LOCAL,
+ VolumeProvider.VOLUME_CONTROL_ABSOLUTE,
+ 10,
+ 3,
+ AudioAttributes.Builder().build(),
+ "",
+ )
+ }
+var Kosmos.localPlaybackStateBuilder by Kosmos.Fixture { PlaybackState.Builder() }
var Kosmos.localMediaController: MediaController by
Kosmos.Fixture {
val appInfo: ApplicationInfo = mock {
@@ -39,22 +53,25 @@
val localSessionToken: MediaSession.Token = MediaSession.Token(0, mock {})
mock {
whenever(packageName).thenReturn(LOCAL_PACKAGE)
- whenever(playbackInfo)
- .thenReturn(
- MediaController.PlaybackInfo(
- MediaController.PlaybackInfo.PLAYBACK_TYPE_LOCAL,
- 0,
- 0,
- 0,
- AudioAttributes.Builder().build(),
- "",
- )
- )
+ whenever(playbackInfo).thenReturn(localPlaybackInfo)
+ whenever(playbackState).thenReturn(localPlaybackStateBuilder.build())
whenever(sessionToken).thenReturn(localSessionToken)
}
}
private const val REMOTE_PACKAGE = "remote.test.pkg"
+var Kosmos.remotePlaybackInfo by
+ Kosmos.Fixture {
+ MediaController.PlaybackInfo(
+ MediaController.PlaybackInfo.PLAYBACK_TYPE_REMOTE,
+ VolumeProvider.VOLUME_CONTROL_ABSOLUTE,
+ 10,
+ 7,
+ AudioAttributes.Builder().build(),
+ "",
+ )
+ }
+var Kosmos.remotePlaybackStateBuilder by Kosmos.Fixture { PlaybackState.Builder() }
var Kosmos.remoteMediaController: MediaController by
Kosmos.Fixture {
val appInfo: ApplicationInfo = mock {
@@ -66,17 +83,8 @@
val remoteSessionToken: MediaSession.Token = MediaSession.Token(0, mock {})
mock {
whenever(packageName).thenReturn(REMOTE_PACKAGE)
- whenever(playbackInfo)
- .thenReturn(
- MediaController.PlaybackInfo(
- MediaController.PlaybackInfo.PLAYBACK_TYPE_REMOTE,
- 0,
- 0,
- 0,
- AudioAttributes.Builder().build(),
- "",
- )
- )
+ whenever(playbackInfo).thenReturn(remotePlaybackInfo)
+ whenever(playbackState).thenReturn(remotePlaybackStateBuilder.build())
whenever(sessionToken).thenReturn(remoteSessionToken)
}
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/MediaOutputKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/MediaOutputKosmos.kt
index fa3a19b..d743558 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/MediaOutputKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/MediaOutputKosmos.kt
@@ -30,13 +30,12 @@
import com.android.systemui.volume.data.repository.FakeLocalMediaRepository
import com.android.systemui.volume.data.repository.FakeMediaControllerRepository
import com.android.systemui.volume.panel.component.mediaoutput.data.repository.FakeLocalMediaRepositoryFactory
-import com.android.systemui.volume.panel.component.mediaoutput.data.repository.LocalMediaRepositoryFactory
import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaDeviceSessionInteractor
import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaOutputActionsInteractor
import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaOutputInteractor
val Kosmos.localMediaRepository by Kosmos.Fixture { FakeLocalMediaRepository() }
-val Kosmos.localMediaRepositoryFactory: LocalMediaRepositoryFactory by
+val Kosmos.localMediaRepositoryFactory by
Kosmos.Fixture { FakeLocalMediaRepositoryFactory { localMediaRepository } }
val Kosmos.mediaOutputActionsInteractor by
@@ -55,6 +54,7 @@
testScope.backgroundScope,
testScope.testScheduler,
mediaControllerRepository,
+ Handler(TestableLooper.get(testCase).looper),
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/mediaoutput/data/repository/FakeLocalMediaRepositoryFactory.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/mediaoutput/data/repository/FakeLocalMediaRepositoryFactory.kt
index 1b3480c..9c902cf 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/mediaoutput/data/repository/FakeLocalMediaRepositoryFactory.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/mediaoutput/data/repository/FakeLocalMediaRepositoryFactory.kt
@@ -18,9 +18,15 @@
import com.android.settingslib.volume.data.repository.LocalMediaRepository
-class FakeLocalMediaRepositoryFactory(
- val provider: (packageName: String?) -> LocalMediaRepository
-) : LocalMediaRepositoryFactory {
+class FakeLocalMediaRepositoryFactory(private val defaultProvider: () -> LocalMediaRepository) :
+ LocalMediaRepositoryFactory {
- override fun create(packageName: String?): LocalMediaRepository = provider(packageName)
+ private val repositories = mutableMapOf<String, LocalMediaRepository>()
+
+ fun setLocalMediaRepository(packageName: String, localMediaRepository: LocalMediaRepository) {
+ repositories[packageName] = localMediaRepository
+ }
+
+ override fun create(packageName: String?): LocalMediaRepository =
+ repositories[packageName] ?: defaultProvider()
}
diff --git a/ravenwood/Android.bp b/ravenwood/Android.bp
index 3337419..bc608c5 100644
--- a/ravenwood/Android.bp
+++ b/ravenwood/Android.bp
@@ -16,6 +16,38 @@
visibility: ["//visibility:public"],
}
+filegroup {
+ name: "ravenwood-services-policies",
+ srcs: [
+ "texts/ravenwood-services-policies.txt",
+ ],
+ visibility: ["//visibility:public"],
+}
+
+filegroup {
+ name: "ravenwood-framework-policies",
+ srcs: [
+ "texts/ravenwood-framework-policies.txt",
+ ],
+ visibility: ["//visibility:public"],
+}
+
+filegroup {
+ name: "ravenwood-standard-options",
+ srcs: [
+ "texts/ravenwood-standard-options.txt",
+ ],
+ visibility: ["//visibility:public"],
+}
+
+filegroup {
+ name: "ravenwood-annotation-allowed-classes",
+ srcs: [
+ "texts/ravenwood-annotation-allowed-classes.txt",
+ ],
+ visibility: ["//visibility:public"],
+}
+
java_library {
name: "ravenwood-annotations-lib",
srcs: [":ravenwood-annotations"],
@@ -155,6 +187,31 @@
visibility: ["//frameworks/base"],
}
+cc_library_shared {
+ name: "libravenwood_runtime",
+ host_supported: true,
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wno-unused-parameter",
+ "-Wthread-safety",
+ ],
+
+ srcs: [
+ "runtime-helper-src/jni/*.cpp",
+ ],
+
+ shared_libs: [
+ "libbase",
+ "liblog",
+ "libnativehelper",
+ "libutils",
+ "libcutils",
+ ],
+ visibility: ["//frameworks/base"],
+}
+
// For collecting the *stats.csv files in a known directory under out/host/linux-x86/testcases/.
// The "test" just shows the available stats filenames.
sh_test_host {
diff --git a/ravenwood/annotations-src/android/ravenwood/annotation/RavenwoodClassLoadHook.java b/ravenwood/annotations-src/android/ravenwood/annotation/RavenwoodClassLoadHook.java
index 7dc197e..7a3142b 100644
--- a/ravenwood/annotations-src/android/ravenwood/annotation/RavenwoodClassLoadHook.java
+++ b/ravenwood/annotations-src/android/ravenwood/annotation/RavenwoodClassLoadHook.java
@@ -28,8 +28,10 @@
* Add this with a fully-specified method name (e.g. {@code "com.package.Class.methodName"})
* of a callback to get a callback at the class load time.
*
- * The method must be {@code public static} with a single argument that takes
- * {@link Class}.
+ * The method must be {@code public static} with a single argument that takes {@link Class}.
+ *
+ * Typically, this is used with {@link #LIBANDROID_LOADING_HOOK}, which will load the necessary
+ * native libraries.
*
* @hide
*/
@@ -37,4 +39,10 @@
@Retention(RetentionPolicy.CLASS)
public @interface RavenwoodClassLoadHook {
String value();
+
+ /**
+ * Class load hook that loads <code>libandroid_runtime</code>.
+ */
+ public static String LIBANDROID_LOADING_HOOK
+ = "com.android.platform.test.ravenwood.runtimehelper.ClassLoadHook.onClassLoaded";
}
diff --git a/ravenwood/bivalenttest/Android.bp b/ravenwood/bivalenttest/Android.bp
index a6b6ed9..2d94894 100644
--- a/ravenwood/bivalenttest/Android.bp
+++ b/ravenwood/bivalenttest/Android.bp
@@ -45,7 +45,6 @@
jni_libs: [
"libravenwoodbivalenttest_jni",
],
- sdk_version: "test_current",
auto_gen_config: true,
}
diff --git a/ravenwood/bivalenttest/AndroidTest.xml b/ravenwood/bivalenttest/AndroidTest.xml
index ac4695b..9e5dd11 100644
--- a/ravenwood/bivalenttest/AndroidTest.xml
+++ b/ravenwood/bivalenttest/AndroidTest.xml
@@ -25,5 +25,8 @@
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="com.android.ravenwood.bivalenttest" />
<option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+
+ <!-- Need to use MODULE_LIBRARIES APIs, so no hidden API check. -->
+ <option name="hidden-api-checks" value="false" />
</test>
</configuration>
diff --git a/ravenwood/bivalenttest/jni/ravenwood_core_test_jni.cpp b/ravenwood/bivalenttest/jni/ravenwood_core_test_jni.cpp
index 83f756e..956d79c 100644
--- a/ravenwood/bivalenttest/jni/ravenwood_core_test_jni.cpp
+++ b/ravenwood/bivalenttest/jni/ravenwood_core_test_jni.cpp
@@ -15,19 +15,70 @@
*/
#include <nativehelper/JNIHelp.h>
+#include <atomic>
#include "jni.h"
#include "utils/Log.h"
#include "utils/misc.h"
+// JNI methods for RavenwoodJniTest
+
static jint add(JNIEnv* env, jclass clazz, jint a, jint b) {
return a + b;
}
-static const JNINativeMethod sMethods[] =
+static const JNINativeMethod sMethods_JniTest[] =
{
{ "add", "(II)I", (void*)add },
};
+// JNI methods for RavenwoodNativeAllocationRegistryTest
+std::atomic<int> numTotalAlloc = 0;
+
+class NarTestData {
+public:
+ NarTestData(jint v): value(v) {
+ numTotalAlloc++;
+ }
+
+ ~NarTestData() {
+ value = -1;
+ numTotalAlloc--;
+ }
+
+ volatile jint value;
+};
+
+static jlong NarTestData_nMalloc(JNIEnv* env, jclass clazz, jint value) {
+ NarTestData* p = new NarTestData(value);
+ return reinterpret_cast<jlong>(p);
+}
+
+static jint NarTestData_nGet(JNIEnv* env, jclass clazz, jlong ptr) {
+ NarTestData* p = reinterpret_cast<NarTestData*>(ptr);
+ return p->value;
+}
+
+static void NarTestData_free(jlong ptr) {
+ NarTestData* p = reinterpret_cast<NarTestData*>(ptr);
+ delete p;
+}
+
+static jlong NarTestData_nGetNativeFinalizer(JNIEnv* env, jclass clazz) {
+ return reinterpret_cast<jlong>(NarTestData_free);
+}
+
+static jint NarTestData_nGetTotalAlloc(JNIEnv* env, jclass clazz) {
+ return numTotalAlloc;
+}
+
+static const JNINativeMethod sMethods_NarTestData[] =
+{
+ { "nMalloc", "(I)J", (void*)NarTestData_nMalloc },
+ { "nGet", "(J)I", (void*)NarTestData_nGet },
+ { "nGetNativeFinalizer", "()J", (void*)NarTestData_nGetNativeFinalizer },
+ { "nGetTotalAlloc", "()I", (void*)NarTestData_nGetTotalAlloc },
+};
+
extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
{
JNIEnv* env = NULL;
@@ -43,7 +94,13 @@
int res = jniRegisterNativeMethods(env,
"com/android/ravenwoodtest/bivalenttest/RavenwoodJniTest",
- sMethods, NELEM(sMethods));
+ sMethods_JniTest, NELEM(sMethods_JniTest));
+ if (res < 0) {
+ return res;
+ }
+ res = jniRegisterNativeMethods(env,
+ "com/android/ravenwoodtest/bivalenttest/RavenwoodNativeAllocationRegistryTest$Data",
+ sMethods_NarTestData, NELEM(sMethods_NarTestData));
if (res < 0) {
return res;
}
diff --git a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodJniTest.java b/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodJniTest.java
index 59467e9..0cc2adc 100644
--- a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodJniTest.java
+++ b/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodJniTest.java
@@ -29,6 +29,10 @@
@RunWith(AndroidJUnit4.class)
public final class RavenwoodJniTest {
static {
+ initializeJni();
+ }
+
+ public static void initializeJni() {
RavenwoodUtils.loadJniLibrary("ravenwoodbivalenttest_jni");
}
diff --git a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodNativeAllocationRegistryTest.java b/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodNativeAllocationRegistryTest.java
new file mode 100644
index 0000000..415b467
--- /dev/null
+++ b/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodNativeAllocationRegistryTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.ravenwoodtest.bivalenttest;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import android.platform.test.ravenwood.RavenwoodRule;
+import android.util.Log;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import libcore.util.NativeAllocationRegistry;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class RavenwoodNativeAllocationRegistryTest {
+ private static final String TAG = RavenwoodNativeAllocationRegistryTest.class.getSimpleName();
+ static {
+ RavenwoodJniTest.initializeJni();
+ }
+
+ @Rule
+ public final RavenwoodRule mRavenwoodRule = new RavenwoodRule();
+
+ private static class Data {
+ private final long mNativePtr;
+
+ private static native long nMalloc(int value);
+ private static native int nGet(long ptr);
+ private static native long nGetNativeFinalizer();
+
+ public static native int nGetTotalAlloc();
+
+ public int get() {
+ return nGet(mNativePtr);
+ }
+
+ private static class NarHolder {
+ public static final NativeAllocationRegistry sRegistry =
+ NativeAllocationRegistry.createMalloced(
+ Data.class.getClassLoader(), nGetNativeFinalizer());
+ }
+
+ public Data(int value) {
+ mNativePtr = nMalloc(value);
+ NarHolder.sRegistry.registerNativeAllocation(this, mNativePtr);
+ }
+ }
+
+ @Test
+ public void testNativeAllocationRegistry() {
+
+ final long timeoutTime = mRavenwoodRule.realCurrentTimeMillis() + 10_000;
+
+ final int startAlloc = Data.nGetTotalAlloc();
+
+ int totalAlloc = 0;
+
+ // Keep allocation new objects, until some get released.
+
+ while (true) {
+ for (int i = 0; i < 1000; i++) {
+ totalAlloc++;
+ Data d = new Data(i);
+ assertEquals(i, d.get());
+ }
+ System.gc();
+
+ final int currentAlloc = Data.nGetTotalAlloc() - startAlloc;
+ Log.i(TAG, "# of currently allocated objects=" + currentAlloc);
+
+ if (currentAlloc < totalAlloc) {
+ break; // Good, some objects have been released;
+ }
+ if (mRavenwoodRule.realCurrentTimeMillis() > timeoutTime) {
+ fail("No objects have been released before timeout");
+ }
+ }
+ }
+}
diff --git a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java
index 21d8019..9d12f85 100644
--- a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java
+++ b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java
@@ -426,4 +426,15 @@
return ENABLE_OPTIONAL_VALIDATION;
}
}
+
+ /**
+ * Returns the "real" result from {@link System#currentTimeMillis()}.
+ *
+ * Currently, it's the same thing as calling {@link System#currentTimeMillis()},
+ * but this one is guaranteeed to return the real value, even when Ravenwood supports
+ * injecting a time to{@link System#currentTimeMillis()}.
+ */
+ public long realCurrentTimeMillis() {
+ return System.currentTimeMillis();
+ }
}
diff --git a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodUtils.java b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodUtils.java
index 37ceac6..99ab327 100644
--- a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodUtils.java
+++ b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodUtils.java
@@ -26,6 +26,15 @@
private RavenwoodUtils() {
}
+ private static final String RAVENWOOD_NATIVE_RUNTIME_NAME = "ravenwood_runtime";
+
+ // LibcoreRavenwoodUtils calls it with reflections.
+ public static void loadRavenwoodNativeRuntime() {
+ if (RavenwoodRule.isOnRavenwood()) {
+ RavenwoodUtils.loadJniLibrary(RAVENWOOD_NATIVE_RUNTIME_NAME);
+ }
+ }
+
/**
* Load a JNI library respecting {@code java.library.path}
* (which reflects {@code LD_LIBRARY_PATH}).
diff --git a/ravenwood/junit-stub-src/android/platform/test/ravenwood/RavenwoodRuleImpl.java b/ravenwood/junit-stub-src/android/platform/test/ravenwood/RavenwoodRuleImpl.java
index e951351b..773a89a 100644
--- a/ravenwood/junit-stub-src/android/platform/test/ravenwood/RavenwoodRuleImpl.java
+++ b/ravenwood/junit-stub-src/android/platform/test/ravenwood/RavenwoodRuleImpl.java
@@ -39,4 +39,8 @@
public static void validate(Statement base, Description description,
boolean enableOptionalValidation) {
}
+
+ public static long realCurrentTimeMillis() {
+ return System.currentTimeMillis();
+ }
}
diff --git a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/runtimehelper/ClassLoadHook.java b/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/runtimehelper/ClassLoadHook.java
index 9057d16..96b7057 100644
--- a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/runtimehelper/ClassLoadHook.java
+++ b/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/runtimehelper/ClassLoadHook.java
@@ -44,6 +44,14 @@
public static final String LIBANDROID_RUNTIME_NAME = "android_runtime";
+ /**
+ * Extra strings needed to pass to register_android_graphics_classes().
+ *
+ * `android.graphics.Graphics` is not actually a class, so we can't use the same initialization
+ * strategy than the "normal" classes. So we just hardcode it here.
+ */
+ public static final String GRAPHICS_EXTRA_INIT_PARAMS = ",android.graphics.Graphics";
+
private static String sInitialDir = new File("").getAbsolutePath();
static {
@@ -98,7 +106,6 @@
private static void loadFrameworkNativeCode() {
// This is called from class-initializers, so no synchronization is needed.
if (sLoadFrameworkNativeCodeCalled) {
- // This method has already been called before.s
return;
}
sLoadFrameworkNativeCodeCalled = true;
@@ -112,7 +119,8 @@
}
if (SKIP_LOADING_LIBANDROID) {
- log("Skip loading " + LIBANDROID_RUNTIME_NAME);
+ log("Skip loading native runtime.");
+ return;
}
// Make sure these properties are not set.
@@ -121,27 +129,39 @@
ensurePropertyNotSet(KEYBOARD_PATHS);
ensurePropertyNotSet(GRAPHICS_NATIVE_CLASSES);
- // Tell libandroid what JNI to use.
- final var jniClasses = getCoreNativeClassesToUse();
- if (jniClasses.isEmpty()) {
- log("No classes require JNI methods, skip loading " + LIBANDROID_RUNTIME_NAME);
+ // Load the libraries, if needed.
+ final var libanrdoidClasses = getClassesWithNativeMethods(sLibandroidClasses);
+ final var libhwuiClasses = getClassesWithNativeMethods(sLibhwuiClasses);
+ if (libanrdoidClasses.isEmpty() && libhwuiClasses.isEmpty()) {
+ log("No classes require JNI methods, skip loading native runtime.");
return;
}
- setProperty(CORE_NATIVE_CLASSES, jniClasses);
- setProperty(GRAPHICS_NATIVE_CLASSES, "");
+ setProperty(CORE_NATIVE_CLASSES, libanrdoidClasses);
+ setProperty(GRAPHICS_NATIVE_CLASSES, libhwuiClasses + GRAPHICS_EXTRA_INIT_PARAMS);
+ log("Loading " + LIBANDROID_RUNTIME_NAME + " for '" + libanrdoidClasses + "' and '"
+ + libhwuiClasses + "'");
RavenwoodUtils.loadJniLibrary(LIBANDROID_RUNTIME_NAME);
}
/**
- * Classes with native methods that are backed by `libandroid_runtime`.
+ * Classes with native methods that are backed by libandroid_runtime.
*
- * At runtime, we check if these classes have any methods, and if so, we'll have
- * `libandroid_runtime` register the native functions.
+ * See frameworks/base/core/jni/platform/host/HostRuntime.cpp
*/
- private static final Class<?>[] sClassesWithLibandroidNativeMethods = {
+ private static final Class<?>[] sLibandroidClasses = {
android.util.Log.class,
- android.os.Parcel.class,
+ };
+
+ /**
+ * Classes with native methods that are backed by libhwui.
+ *
+ * See frameworks/base/libs/hwui/apex/LayoutlibLoader.cpp
+ */
+ private static final Class<?>[] sLibhwuiClasses = {
+ android.graphics.Interpolator.class,
+ android.graphics.Matrix.class,
+ android.graphics.Path.class,
};
/**
@@ -157,17 +177,15 @@
}
/**
- * Create a list of classes as comma-separated that require JNI methods to be set up.
- *
- * <p>This list is used by frameworks/base/core/jni/LayoutlibLoader.cpp to decide
- * what JNI methods to set up.
+ * Create a list of classes as comma-separated that require JNI methods to be set up from
+ * a given class list, ignoring classes with no native methods.
*/
- private static String getCoreNativeClassesToUse() {
+ private static String getClassesWithNativeMethods(Class<?>[] classes) {
final var coreNativeClassesToLoad = new ArrayList<String>();
- for (var clazz : sClassesWithLibandroidNativeMethods) {
+ for (var clazz : classes) {
if (hasNativeMethod(clazz)) {
- log("Class %s has native methods", clazz);
+ log("Class %s has native methods", clazz.getCanonicalName());
coreNativeClassesToLoad.add(clazz.getName());
}
}
diff --git a/ravenwood/runtime-helper-src/jni/ravenwood_runtime.cpp b/ravenwood/runtime-helper-src/jni/ravenwood_runtime.cpp
new file mode 100644
index 0000000..8e3a21d
--- /dev/null
+++ b/ravenwood/runtime-helper-src/jni/ravenwood_runtime.cpp
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <nativehelper/JNIHelp.h>
+#include "jni.h"
+#include "utils/Log.h"
+#include "utils/misc.h"
+
+
+typedef void (*FreeFunction)(void*);
+
+static void NativeAllocationRegistry_applyFreeFunction(JNIEnv*,
+ jclass,
+ jlong freeFunction,
+ jlong ptr) {
+ void* nativePtr = reinterpret_cast<void*>(static_cast<uintptr_t>(ptr));
+ FreeFunction nativeFreeFunction
+ = reinterpret_cast<FreeFunction>(static_cast<uintptr_t>(freeFunction));
+ nativeFreeFunction(nativePtr);
+}
+
+static const JNINativeMethod sMethods_NAR[] =
+{
+ { "applyFreeFunction", "(JJ)V", (void*)NativeAllocationRegistry_applyFreeFunction },
+};
+
+extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
+{
+ JNIEnv* env = NULL;
+ jint result = -1;
+
+ if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
+ ALOGE("GetEnv failed!");
+ return result;
+ }
+ ALOG_ASSERT(env, "Could not retrieve the env!");
+
+ ALOGI("%s: JNI_OnLoad", __FILE__);
+
+ // Initialize the Ravenwood version of NativeAllocationRegistry.
+ // We don't use this JNI on the device side, but if we ever have to do, skip this part.
+#ifndef __ANDROID__
+ int res = jniRegisterNativeMethods(env, "libcore/util/NativeAllocationRegistry",
+ sMethods_NAR, NELEM(sMethods_NAR));
+ if (res < 0) {
+ return res;
+ }
+#endif
+
+ return JNI_VERSION_1_4;
+}
diff --git a/ravenwood/runtime-helper-src/libcore-fake/libcore/ravenwood/LibcoreRavenwoodUtils.java b/ravenwood/runtime-helper-src/libcore-fake/libcore/ravenwood/LibcoreRavenwoodUtils.java
new file mode 100644
index 0000000..839b62a
--- /dev/null
+++ b/ravenwood/runtime-helper-src/libcore-fake/libcore/ravenwood/LibcoreRavenwoodUtils.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package libcore.ravenwood;
+
+public class LibcoreRavenwoodUtils {
+ private LibcoreRavenwoodUtils() {
+ }
+
+ public static void loadRavenwoodNativeRuntime() {
+ // TODO Stop using reflections.
+ // We need to call RavenwoodUtils.loadRavenwoodNativeRuntime(), but due to the build
+ // structure complexity, we can't refer to to this method directly from here,
+ // so let's use reflections for now...
+ try {
+ final var clazz = Class.forName("android.platform.test.ravenwood.RavenwoodUtils");
+ final var method = clazz.getMethod("loadRavenwoodNativeRuntime");
+ method.invoke(null);
+ } catch (Throwable th) {
+ throw new IllegalStateException("Failed to load Ravenwood native runtime", th);
+ }
+ }
+}
diff --git a/ravenwood/runtime-helper-src/libcore-fake/libcore/util/NativeAllocationRegistry.java b/ravenwood/runtime-helper-src/libcore-fake/libcore/util/NativeAllocationRegistry.java
new file mode 100644
index 0000000..93861e8
--- /dev/null
+++ b/ravenwood/runtime-helper-src/libcore-fake/libcore/util/NativeAllocationRegistry.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package libcore.util;
+
+import libcore.ravenwood.LibcoreRavenwoodUtils;
+
+import java.lang.ref.Cleaner;
+import java.lang.ref.Reference;
+
+/**
+ * Re-implementation of ART's NativeAllocationRegistry for Ravenwood.
+ * - We don't track the native allocation size on Ravenwood.
+ * - sun.misc.Cleaner isn't available on the desktop JVM, so we use java.lang.ref.Cleaner.
+ * (Should ART switch to java.lang.ref.Cleaner?)
+ */
+public class NativeAllocationRegistry {
+ static {
+ // Initialize the JNI method.
+ LibcoreRavenwoodUtils.loadRavenwoodNativeRuntime();
+ }
+
+ private final long mFreeFunction;
+ private static final Cleaner sCleaner = Cleaner.create();
+
+ public static NativeAllocationRegistry createNonmalloced(
+ ClassLoader classLoader, long freeFunction, long size) {
+ return new NativeAllocationRegistry(classLoader, freeFunction, size, false);
+ }
+
+ public static NativeAllocationRegistry createMalloced(
+ ClassLoader classLoader, long freeFunction, long size) {
+ return new NativeAllocationRegistry(classLoader, freeFunction, size, true);
+ }
+
+ public static NativeAllocationRegistry createMalloced(
+ ClassLoader classLoader, long freeFunction) {
+ return new NativeAllocationRegistry(classLoader, freeFunction, 0, true);
+ }
+
+ public NativeAllocationRegistry(ClassLoader classLoader, long freeFunction, long size) {
+ this(classLoader, freeFunction, size, size == 0);
+ }
+
+ private NativeAllocationRegistry(ClassLoader classLoader, long freeFunction, long size,
+ boolean mallocAllocation) {
+ if (size < 0) {
+ throw new IllegalArgumentException("Invalid native allocation size: " + size);
+ }
+ mFreeFunction = freeFunction;
+ }
+
+ public Runnable registerNativeAllocation(Object referent, long nativePtr) {
+ if (referent == null) {
+ throw new IllegalArgumentException("referent is null");
+ }
+ if (nativePtr == 0) {
+ throw new IllegalArgumentException("nativePtr is null");
+ }
+
+ final Runnable releaser = () -> {
+ applyFreeFunction(mFreeFunction, nativePtr);
+ };
+ sCleaner.register(referent, releaser);
+
+ // Ensure that cleaner doesn't get invoked before we enable it.
+ Reference.reachabilityFence(referent);
+ return releaser;
+ }
+
+ /**
+ * Calls {@code freeFunction}({@code nativePtr}).
+ */
+ public static native void applyFreeFunction(long freeFunction, long nativePtr);
+}
+
diff --git a/ravenwood/scripts/ravenwood-stats-collector.sh b/ravenwood/scripts/ravenwood-stats-collector.sh
index beacde2..cf58bd2 100755
--- a/ravenwood/scripts/ravenwood-stats-collector.sh
+++ b/ravenwood/scripts/ravenwood-stats-collector.sh
@@ -24,6 +24,8 @@
# Where the input files are.
path=$ANDROID_BUILD_TOP/out/host/linux-x86/testcases/ravenwood-stats-checker/x86_64/
+timestamp="$(date --iso-8601=seconds)"
+
m() {
${ANDROID_BUILD_TOP}/build/soong/soong_ui.bash --make-mode "$@"
}
@@ -39,15 +41,15 @@
local jar=$1
local file=$2
- # Use sed to remove the header + prepend the jar filename.
- sed -e '1d' -e "s/^/$jar,/" $file
+ # Remove the header row, and prepend the columns.
+ sed -e '1d' -e "s/^/$jar,$timestamp,/" $file
}
collect_stats() {
local out="$1"
{
# Copy the header, with the first column appended.
- echo -n "Jar,"
+ echo -n "Jar,Generated Date,"
head -n 1 hoststubgen_framework-minus-apex_stats.csv
dump "framework-minus-apex" hoststubgen_framework-minus-apex_stats.csv
@@ -61,7 +63,7 @@
local out="$1"
{
# Copy the header, with the first column appended.
- echo -n "Jar,"
+ echo -n "Jar,Generated Date,"
head -n 1 hoststubgen_framework-minus-apex_apis.csv
dump "framework-minus-apex" hoststubgen_framework-minus-apex_apis.csv
diff --git a/ravenwood/texts/ravenwood-annotation-allowed-classes.txt b/ravenwood/texts/ravenwood-annotation-allowed-classes.txt
index 243e224..e452299 100644
--- a/ravenwood/texts/ravenwood-annotation-allowed-classes.txt
+++ b/ravenwood/texts/ravenwood-annotation-allowed-classes.txt
@@ -236,7 +236,11 @@
android.accounts.Account
+android.graphics.Bitmap$Config
android.graphics.Insets
+android.graphics.Interpolator
+android.graphics.Matrix
+android.graphics.Path
android.graphics.Point
android.graphics.PointF
android.graphics.Rect
diff --git a/ravenwood/texts/framework-minus-apex-ravenwood-policies.txt b/ravenwood/texts/ravenwood-framework-policies.txt
similarity index 100%
rename from ravenwood/texts/framework-minus-apex-ravenwood-policies.txt
rename to ravenwood/texts/ravenwood-framework-policies.txt
diff --git a/ravenwood/texts/services.core-ravenwood-policies.txt b/ravenwood/texts/ravenwood-services-policies.txt
similarity index 100%
rename from ravenwood/texts/services.core-ravenwood-policies.txt
rename to ravenwood/texts/ravenwood-services-policies.txt
diff --git a/services/accessibility/accessibility.aconfig b/services/accessibility/accessibility.aconfig
index e66fe1b..82579d8 100644
--- a/services/accessibility/accessibility.aconfig
+++ b/services/accessibility/accessibility.aconfig
@@ -130,7 +130,7 @@
flag {
name: "manager_avoid_receiver_timeout"
namespace: "accessibility"
- description: "Avoid broadcast receiver timeout by offloading potentially slow operations to the background thread."
+ description: "Register receivers on background handler so they have more time to complete"
bug: "333890389"
metadata {
purpose: PURPOSE_BUGFIX
diff --git a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
index 8a699ef..42f168b 100644
--- a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
@@ -44,10 +44,12 @@
import android.accessibilityservice.IAccessibilityServiceConnection;
import android.accessibilityservice.IBrailleDisplayController;
import android.accessibilityservice.MagnificationConfig;
+import android.annotation.EnforcePermission;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.SuppressLint;
+import android.annotation.PermissionManuallyEnforced;
+import android.annotation.RequiresNoPermission;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
@@ -68,6 +70,7 @@
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
+import android.os.PermissionEnforcer;
import android.os.PowerManager;
import android.os.RemoteCallback;
import android.os.RemoteException;
@@ -121,7 +124,6 @@
* This class represents an accessibility client - either an AccessibilityService or a UiAutomation.
* It is responsible for behavior common to both types of clients.
*/
-@SuppressWarnings("MissingPermissionAnnotation")
abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServiceConnection.Stub
implements ServiceConnection, IBinder.DeathRecipient, KeyEventDispatcher.KeyEventFilter,
FingerprintGestureDispatcher.FingerprintGestureClient {
@@ -339,6 +341,7 @@
AccessibilityTrace trace, WindowManagerInternal windowManagerInternal,
SystemActionPerformer systemActionPerfomer,
AccessibilityWindowManager a11yWindowManager) {
+ super(PermissionEnforcer.fromContext(context));
mContext = context;
mWindowManagerService = windowManagerInternal;
mId = id;
@@ -469,6 +472,7 @@
return (mEventTypes != 0 && mService != null);
}
+ @RequiresNoPermission
@Override
public void setOnKeyEventResult(boolean handled, int sequence) {
if (svcConnTracingEnabled()) {
@@ -482,6 +486,7 @@
}
}
+ @RequiresNoPermission
@Override
public AccessibilityServiceInfo getServiceInfo() {
if (svcConnTracingEnabled()) {
@@ -501,6 +506,7 @@
: AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) | mEventTypes;
}
+ @RequiresNoPermission
@Override
public void setServiceInfo(AccessibilityServiceInfo info) {
if (svcConnTracingEnabled()) {
@@ -536,16 +542,19 @@
}
}
+ @RequiresNoPermission
@Override
public void setInstalledAndEnabledServices(List<AccessibilityServiceInfo> infos) {
return;
}
+ @RequiresNoPermission
@Override
public List<AccessibilityServiceInfo> getInstalledAndEnabledServices() {
return null;
}
+ @RequiresNoPermission
@Override
public void setAttributionTag(String attributionTag) {
mAttributionTag = attributionTag;
@@ -558,6 +567,7 @@
protected abstract boolean hasRightsToCurrentUserLocked();
@Nullable
+ @RequiresNoPermission
@Override
public AccessibilityWindowInfo.WindowListSparseArray getWindows() {
if (svcConnTracingEnabled()) {
@@ -606,6 +616,7 @@
mDisplayTypes = displayTypes;
}
+ @RequiresNoPermission
@Override
public AccessibilityWindowInfo getWindow(int windowId) {
if (svcConnTracingEnabled()) {
@@ -646,6 +657,7 @@
}
}
+ @RequiresNoPermission
@Override
public String[] findAccessibilityNodeInfosByViewId(int accessibilityWindowId,
long accessibilityNodeId, String viewIdResName, int interactionId,
@@ -722,6 +734,7 @@
return null;
}
+ @RequiresNoPermission
@Override
public String[] findAccessibilityNodeInfosByText(int accessibilityWindowId,
long accessibilityNodeId, String text, int interactionId,
@@ -797,6 +810,7 @@
return null;
}
+ @RequiresNoPermission
@Override
public String[] findAccessibilityNodeInfoByAccessibilityId(
int accessibilityWindowId, long accessibilityNodeId, int interactionId,
@@ -875,6 +889,7 @@
return null;
}
+ @RequiresNoPermission
@Override
public String[] findFocus(int accessibilityWindowId, long accessibilityNodeId,
int focusType, int interactionId,
@@ -952,6 +967,7 @@
return null;
}
+ @RequiresNoPermission
@Override
public String[] focusSearch(int accessibilityWindowId, long accessibilityNodeId,
int direction, int interactionId,
@@ -1028,6 +1044,7 @@
return null;
}
+ @RequiresNoPermission
@Override
public void sendGesture(int sequence, ParceledListSlice gestureSteps) {
if (svcConnTracingEnabled()) {
@@ -1036,6 +1053,7 @@
}
}
+ @RequiresNoPermission
@Override
public void dispatchGesture(int sequence, ParceledListSlice gestureSteps, int displayId) {
if (svcConnTracingEnabled()) {
@@ -1044,6 +1062,7 @@
}
}
+ @RequiresNoPermission
@Override
public boolean performAccessibilityAction(int accessibilityWindowId,
long accessibilityNodeId, int action, Bundle arguments, int interactionId,
@@ -1075,6 +1094,7 @@
action, arguments, interactionId, callback, mFetchFlags, interrogatingTid);
}
+ @RequiresNoPermission
@Override
public boolean performGlobalAction(int action) {
if (svcConnTracingEnabled()) {
@@ -1093,6 +1113,7 @@
}
}
+ @RequiresNoPermission
@Override
public @NonNull List<AccessibilityNodeInfo.AccessibilityAction> getSystemActions() {
if (svcConnTracingEnabled()) {
@@ -1111,6 +1132,7 @@
}
}
+ @RequiresNoPermission
@Override
public boolean isFingerprintGestureDetectionAvailable() {
if (svcConnTracingEnabled()) {
@@ -1133,6 +1155,7 @@
}
@Nullable
+ @RequiresNoPermission
@Override
public MagnificationConfig getMagnificationConfig(int displayId) {
if (svcConnTracingEnabled()) {
@@ -1151,6 +1174,7 @@
}
}
+ @RequiresNoPermission
@Override
public float getMagnificationScale(int displayId) {
if (svcConnTracingEnabled()) {
@@ -1169,6 +1193,7 @@
}
}
+ @RequiresNoPermission
@Override
public Region getMagnificationRegion(int displayId) {
if (svcConnTracingEnabled()) {
@@ -1193,6 +1218,7 @@
}
+ @RequiresNoPermission
@Override
public Region getCurrentMagnificationRegion(int displayId) {
if (svcConnTracingEnabled()) {
@@ -1216,6 +1242,7 @@
}
}
+ @RequiresNoPermission
@Override
public float getMagnificationCenterX(int displayId) {
if (svcConnTracingEnabled()) {
@@ -1237,6 +1264,7 @@
}
}
+ @RequiresNoPermission
@Override
public float getMagnificationCenterY(int displayId) {
if (svcConnTracingEnabled()) {
@@ -1258,6 +1286,7 @@
}
}
+ @RequiresNoPermission
@Override
public boolean resetMagnification(int displayId, boolean animate) {
if (svcConnTracingEnabled()) {
@@ -1282,6 +1311,7 @@
}
}
+ @RequiresNoPermission
@Override
public boolean resetCurrentMagnification(int displayId, boolean animate) {
if (svcConnTracingEnabled()) {
@@ -1307,6 +1337,7 @@
}
}
+ @RequiresNoPermission
@Override
public boolean setMagnificationConfig(int displayId,
@NonNull MagnificationConfig config, boolean animate) {
@@ -1333,6 +1364,7 @@
}
}
+ @RequiresNoPermission
@Override
public void setMagnificationCallbackEnabled(int displayId, boolean enabled) {
if (svcConnTracingEnabled()) {
@@ -1351,6 +1383,7 @@
return mInvocationHandler.isMagnificationCallbackEnabled(displayId);
}
+ @RequiresNoPermission
@Override
public void setSoftKeyboardCallbackEnabled(boolean enabled) {
if (svcConnTracingEnabled()) {
@@ -1364,6 +1397,7 @@
}
}
+ @RequiresNoPermission
@Override
public void takeScreenshotOfWindow(int accessibilityWindowId, int interactionId,
ScreenCapture.ScreenCaptureListener listener,
@@ -1414,6 +1448,7 @@
}
}
+ @RequiresNoPermission
@Override
public void takeScreenshot(int displayId, RemoteCallback callback) {
if (svcConnTracingEnabled()) {
@@ -1553,6 +1588,7 @@
}
@Override
+ @PermissionManuallyEnforced
public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return;
synchronized (mLock) {
@@ -1649,6 +1685,7 @@
* @param displayId The id of the logical display that was added.
* @return window token.
*/
+ @RequiresNoPermission
@Override
public IBinder getOverlayWindowToken(int displayId) {
if (svcConnTracingEnabled()) {
@@ -1670,6 +1707,7 @@
* @param token The token
* @return window id
*/
+ @RequiresNoPermission
@Override
public int getWindowIdForLeashToken(@NonNull IBinder token) {
if (svcConnTracingEnabled()) {
@@ -2523,6 +2561,7 @@
return mSendMotionEvents;
}
+ @RequiresNoPermission
@Override
public void setGestureDetectionPassthroughRegion(int displayId, Region region) {
if (svcConnTracingEnabled()) {
@@ -2537,6 +2576,7 @@
}
}
+ @RequiresNoPermission
@Override
public void setTouchExplorationPassthroughRegion(int displayId, Region region) {
if (svcConnTracingEnabled()) {
@@ -2551,6 +2591,7 @@
}
}
+ @RequiresNoPermission
@Override
public void setFocusAppearance(int strokeWidth, int color) {
if (svcConnTracingEnabled()) {
@@ -2558,6 +2599,7 @@
}
}
+ @RequiresNoPermission
@Override
public void setCacheEnabled(boolean enabled) {
if (svcConnTracingEnabled()) {
@@ -2574,6 +2616,7 @@
}
}
+ @RequiresNoPermission
@Override
public void logTrace(long timestamp, String where, long loggingTypes, String callingParams,
int processId, long threadId, int callingUid, Bundle callingStack) {
@@ -2629,6 +2672,7 @@
mTrace.logTrace(TRACE_WM + "." + methodName, FLAGS_WINDOW_MANAGER_INTERNAL, params);
}
+ @RequiresNoPermission
@Override
public void setServiceDetectsGesturesEnabled(int displayId, boolean mode) {
final long identity = Binder.clearCallingIdentity();
@@ -2647,6 +2691,7 @@
return false;
}
+ @RequiresNoPermission
@Override
public void requestTouchExploration(int displayId) {
final long identity = Binder.clearCallingIdentity();
@@ -2657,6 +2702,7 @@
}
}
+ @RequiresNoPermission
@Override
public void requestDragging(int displayId, int pointerId) {
final long identity = Binder.clearCallingIdentity();
@@ -2667,6 +2713,7 @@
}
}
+ @RequiresNoPermission
@Override
public void requestDelegating(int displayId) {
final long identity = Binder.clearCallingIdentity();
@@ -2677,6 +2724,7 @@
}
}
+ @RequiresNoPermission
@Override
public void onDoubleTap(int displayId) {
final long identity = Binder.clearCallingIdentity();
@@ -2687,6 +2735,7 @@
}
}
+ @RequiresNoPermission
@Override
public void onDoubleTapAndHold(int displayId) {
final long identity = Binder.clearCallingIdentity();
@@ -2700,6 +2749,7 @@
/**
* Sets the scaling factor for animations.
*/
+ @RequiresNoPermission
@Override
public void setAnimationScale(float scale) {
final long identity = Binder.clearCallingIdentity();
@@ -2717,6 +2767,7 @@
}
}
+ @RequiresNoPermission
@Override
public void attachAccessibilityOverlayToDisplay(
int interactionId,
@@ -2733,6 +2784,7 @@
}
}
+ @RequiresNoPermission
@Override
public void attachAccessibilityOverlayToWindow(
int interactionId,
@@ -2779,12 +2831,14 @@
}
@Override
- @SuppressLint("AndroidFrameworkRequiresPermission") // Unsupported in Abstract class
+ @EnforcePermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public void connectBluetoothBrailleDisplay(String bluetoothAddress,
IBrailleDisplayController controller) {
+ connectBluetoothBrailleDisplay_enforcePermission();
throw new UnsupportedOperationException();
}
+ @RequiresNoPermission
@Override
public void connectUsbBrailleDisplay(UsbDevice usbDevice,
IBrailleDisplayController controller) {
@@ -2792,8 +2846,9 @@
}
@Override
- @SuppressLint("AndroidFrameworkRequiresPermission") // Unsupported in Abstract class
+ @EnforcePermission(android.Manifest.permission.MANAGE_ACCESSIBILITY)
public void setTestBrailleDisplayData(List<Bundle> brailleDisplays) {
+ setTestBrailleDisplayData_enforcePermission();
throw new UnsupportedOperationException();
}
}
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index ad869a1..c70b641 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -852,7 +852,7 @@
}
private void registerBroadcastReceivers() {
- mPackageMonitor = new PackageMonitor() {
+ mPackageMonitor = new PackageMonitor(true) {
@Override
public void onSomePackagesChanged() {
if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_PACKAGE_BROADCAST_RECEIVER)) {
@@ -986,6 +986,8 @@
intentFilter.addAction(Intent.ACTION_USER_REMOVED);
intentFilter.addAction(Intent.ACTION_SETTING_RESTORED);
+ Handler receiverHandler =
+ Flags.managerAvoidReceiverTimeout() ? BackgroundThread.getHandler() : null;
mContext.registerReceiverAsUser(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -994,13 +996,46 @@
"context=" + context + ";intent=" + intent);
}
- if (com.android.server.accessibility.Flags.managerAvoidReceiverTimeout()) {
- BackgroundThread.getHandler().post(() -> processBroadcast(intent));
- } else {
- processBroadcast(intent);
+ String action = intent.getAction();
+ if (Intent.ACTION_USER_SWITCHED.equals(action)) {
+ switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
+ } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) {
+ unlockUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
+ } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
+ removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
+ } else if (Intent.ACTION_SETTING_RESTORED.equals(action)) {
+ final String which = intent.getStringExtra(Intent.EXTRA_SETTING_NAME);
+ if (Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES.equals(which)) {
+ synchronized (mLock) {
+ restoreEnabledAccessibilityServicesLocked(
+ intent.getStringExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE),
+ intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE),
+ intent.getIntExtra(Intent.EXTRA_SETTING_RESTORED_FROM_SDK_INT,
+ 0));
+ }
+ } else if (ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED.equals(which)) {
+ synchronized (mLock) {
+ restoreLegacyDisplayMagnificationNavBarIfNeededLocked(
+ intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE),
+ intent.getIntExtra(Intent.EXTRA_SETTING_RESTORED_FROM_SDK_INT,
+ 0));
+ }
+ } else if (Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS.equals(which)) {
+ synchronized (mLock) {
+ restoreAccessibilityButtonTargetsLocked(
+ intent.getStringExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE),
+ intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE));
+ }
+ } else if (Settings.Secure.ACCESSIBILITY_QS_TARGETS.equals(which)) {
+ if (!android.view.accessibility.Flags.a11yQsShortcut()) {
+ return;
+ }
+ restoreAccessibilityQsTargets(
+ intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE));
+ }
}
}
- }, UserHandle.ALL, intentFilter, null, null);
+ }, UserHandle.ALL, intentFilter, null, receiverHandler);
final IntentFilter filter = new IntentFilter();
filter.addAction(SafetyCenterManager.ACTION_SAFETY_CENTER_ENABLED_CHANGED);
@@ -2000,19 +2035,6 @@
mA11yWindowManager.onTouchInteractionEnd();
}
- private void processBroadcast(Intent intent) {
- String action = intent.getAction();
- if (Intent.ACTION_USER_SWITCHED.equals(action)) {
- switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
- } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) {
- unlockUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
- } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
- removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
- } else if (Intent.ACTION_SETTING_RESTORED.equals(action)) {
- restoreSetting(intent);
- }
- }
-
@VisibleForTesting
void switchUser(int userId) {
mMagnificationController.updateUserIdIfNeeded(userId);
@@ -2105,38 +2127,6 @@
getMagnificationController().onUserRemoved(userId);
}
- private void restoreSetting(Intent intent) {
- final String which = intent.getStringExtra(Intent.EXTRA_SETTING_NAME);
- if (Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES.equals(which)) {
- synchronized (mLock) {
- restoreEnabledAccessibilityServicesLocked(
- intent.getStringExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE),
- intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE),
- intent.getIntExtra(Intent.EXTRA_SETTING_RESTORED_FROM_SDK_INT,
- 0));
- }
- } else if (ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED.equals(which)) {
- synchronized (mLock) {
- restoreLegacyDisplayMagnificationNavBarIfNeededLocked(
- intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE),
- intent.getIntExtra(Intent.EXTRA_SETTING_RESTORED_FROM_SDK_INT,
- 0));
- }
- } else if (Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS.equals(which)) {
- synchronized (mLock) {
- restoreAccessibilityButtonTargetsLocked(
- intent.getStringExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE),
- intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE));
- }
- } else if (Settings.Secure.ACCESSIBILITY_QS_TARGETS.equals(which)) {
- if (!android.view.accessibility.Flags.a11yQsShortcut()) {
- return;
- }
- restoreAccessibilityQsTargets(
- intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE));
- }
- }
-
// Called only during settings restore; currently supports only the owner user
// TODO: http://b/22388012
void restoreEnabledAccessibilityServicesLocked(String oldSetting, String newSetting,
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
index 1f65e15..786d167 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
@@ -30,10 +30,10 @@
import android.accessibilityservice.IAccessibilityServiceClient;
import android.accessibilityservice.IBrailleDisplayController;
import android.accessibilityservice.TouchInteractionController;
+import android.annotation.EnforcePermission;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.RequiresPermission;
-import android.annotation.SuppressLint;
+import android.annotation.RequiresNoPermission;
import android.annotation.UserIdInt;
import android.app.PendingIntent;
import android.bluetooth.BluetoothAdapter;
@@ -79,7 +79,6 @@
* passed to the service it represents as soon it is bound. It also serves as the
* connection for the service.
*/
-@SuppressWarnings("MissingPermissionAnnotation")
class AccessibilityServiceConnection extends AbstractAccessibilityServiceConnection {
private static final String LOG_TAG = "AccessibilityServiceConnection";
@@ -110,6 +109,7 @@
mUserId = userId;
}
+ @RequiresNoPermission
@Override
public void sessionCreated(IAccessibilityInputMethodSession session, int id) {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "ASC.sessionCreated");
@@ -196,6 +196,7 @@
return mSecurityPolicy.canRetrieveWindowContentLocked(this) && mRetrieveInteractiveWindows;
}
+ @RequiresNoPermission
@Override
public void disableSelf() {
if (svcConnTracingEnabled()) {
@@ -253,6 +254,7 @@
}
}
+ @RequiresNoPermission
@Override
public AccessibilityServiceInfo getServiceInfo() {
return mAccessibilityServiceInfo;
@@ -330,6 +332,7 @@
return false;
}
+ @RequiresNoPermission
@Override
public boolean setSoftKeyboardShowMode(int showMode) {
if (svcConnTracingEnabled()) {
@@ -351,6 +354,7 @@
}
}
+ @RequiresNoPermission
@Override
public int getSoftKeyboardShowMode() {
if (svcConnTracingEnabled()) {
@@ -365,6 +369,7 @@
}
}
+ @RequiresNoPermission
@Override
public boolean switchToInputMethod(String imeId) {
if (svcConnTracingEnabled()) {
@@ -386,6 +391,7 @@
return result;
}
+ @RequiresNoPermission
@Override
@AccessibilityService.SoftKeyboardController.EnableImeResult
public int setInputMethodEnabled(String imeId, boolean enabled) throws SecurityException {
@@ -421,6 +427,7 @@
return ENABLE_IME_FAIL_UNKNOWN;
}
+ @RequiresNoPermission
@Override
public boolean isAccessibilityButtonAvailable() {
if (svcConnTracingEnabled()) {
@@ -535,6 +542,7 @@
}
}
+ @RequiresNoPermission
@Override
public void dispatchGesture(int sequence, ParceledListSlice gestureSteps, int displayId) {
synchronized (mLock) {
@@ -569,6 +577,7 @@
}
}
+ @RequiresNoPermission
@Override
public void setFocusAppearance(int strokeWidth, int color) {
AccessibilityUserState userState = mUserStateWeakReference.get();
@@ -683,16 +692,15 @@
* {@link android.bluetooth.BluetoothDevice#getAddress()}.
*/
@Override
- @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
+ @EnforcePermission(Manifest.permission.BLUETOOTH_CONNECT)
public void connectBluetoothBrailleDisplay(
@NonNull String bluetoothAddress, @NonNull IBrailleDisplayController controller) {
+ connectBluetoothBrailleDisplay_enforcePermission();
if (!android.view.accessibility.Flags.brailleDisplayHid()) {
throw new IllegalStateException("Flag BRAILLE_DISPLAY_HID not enabled");
}
Objects.requireNonNull(bluetoothAddress);
Objects.requireNonNull(controller);
- mContext.enforceCallingPermission(Manifest.permission.BLUETOOTH_CONNECT,
- "Missing BLUETOOTH_CONNECT permission");
if (!BluetoothAdapter.checkBluetoothAddress(bluetoothAddress)) {
throw new IllegalArgumentException(
bluetoothAddress + " is not a valid Bluetooth address");
@@ -728,7 +736,7 @@
*
* <p>The caller package must already have USB permission for this {@link UsbDevice}.
*/
- @SuppressLint("MissingPermission") // system_server has the required MANAGE_USB permission
+ @RequiresNoPermission
@Override
@NonNull
public void connectUsbBrailleDisplay(@NonNull UsbDevice usbDevice,
@@ -783,11 +791,10 @@
}
@Override
- @RequiresPermission(Manifest.permission.MANAGE_ACCESSIBILITY)
+ @EnforcePermission(Manifest.permission.MANAGE_ACCESSIBILITY)
public void setTestBrailleDisplayData(List<Bundle> brailleDisplays) {
+ setTestBrailleDisplayData_enforcePermission();
// Enforce that this TestApi is only called by trusted (test) callers.
- mContext.enforceCallingPermission(Manifest.permission.MANAGE_ACCESSIBILITY,
- "Missing MANAGE_ACCESSIBILITY permission");
mTestBrailleDisplays = brailleDisplays;
}
diff --git a/services/accessibility/java/com/android/server/accessibility/ProxyAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/ProxyAccessibilityServiceConnection.java
index b77b2be..4cb3d24 100644
--- a/services/accessibility/java/com/android/server/accessibility/ProxyAccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/ProxyAccessibilityServiceConnection.java
@@ -24,6 +24,8 @@
import android.accessibilityservice.IAccessibilityServiceClient;
import android.accessibilityservice.MagnificationConfig;
import android.annotation.NonNull;
+import android.annotation.PermissionManuallyEnforced;
+import android.annotation.RequiresNoPermission;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ApplicationInfo;
@@ -64,7 +66,6 @@
*
* TODO(241429275): Initialize this when a proxy is registered.
*/
-@SuppressWarnings("MissingPermissionAnnotation")
public class ProxyAccessibilityServiceConnection extends AccessibilityServiceConnection {
private static final String LOG_TAG = "ProxyAccessibilityServiceConnection";
@@ -125,6 +126,7 @@
*
* @param infos the list of enabled and installed services.
*/
+ @RequiresNoPermission
@Override
public void setInstalledAndEnabledServices(@NonNull List<AccessibilityServiceInfo> infos) {
final long identity = Binder.clearCallingIdentity();
@@ -215,6 +217,7 @@
}
}
+ @RequiresNoPermission
@Override
@NonNull
public List<AccessibilityServiceInfo> getInstalledAndEnabledServices() {
@@ -224,6 +227,7 @@
}
}
+ @RequiresNoPermission
@Override
public AccessibilityWindowInfo.WindowListSparseArray getWindows() {
final AccessibilityWindowInfo.WindowListSparseArray allWindows = super.getWindows();
@@ -235,6 +239,7 @@
return displayWindows;
}
+ @RequiresNoPermission
@Override
public void setFocusAppearance(int strokeWidth, int color) {
synchronized (mLock) {
@@ -272,6 +277,7 @@
return mFocusColor;
}
+ @RequiresNoPermission
@Override
int resolveAccessibilityWindowIdForFindFocusLocked(int windowId, int focusType) {
if (windowId == AccessibilityWindowInfo.ANY_WINDOW_ID) {
@@ -314,12 +320,14 @@
}
/** @throws UnsupportedOperationException since a proxy does not need fingerprint hardware */
+ @RequiresNoPermission
@Override
public boolean isCapturingFingerprintGestures() throws UnsupportedOperationException {
throw new UnsupportedOperationException("isCapturingFingerprintGestures is not supported");
}
/** @throws UnsupportedOperationException since a proxy does not need fingerprint hardware */
+ @RequiresNoPermission
@Override
public void onFingerprintGestureDetectionActiveChanged(boolean active)
throws UnsupportedOperationException {
@@ -328,12 +336,14 @@
}
/** @throws UnsupportedOperationException since a proxy does not need fingerprint hardware */
+ @RequiresNoPermission
@Override
public void onFingerprintGesture(int gesture) throws UnsupportedOperationException {
throw new UnsupportedOperationException("onFingerprintGesture is not supported");
}
/** @throws UnsupportedOperationException since a proxy does not need fingerprint hardware */
+ @RequiresNoPermission
@Override
public boolean isFingerprintGestureDetectionAvailable() throws UnsupportedOperationException {
throw new UnsupportedOperationException("isFingerprintGestureDetectionAvailable is not"
@@ -341,6 +351,7 @@
}
/** @throws UnsupportedOperationException since a proxy is not a Service */
+ @RequiresNoPermission
@Override
public void onServiceConnected(ComponentName name, IBinder service)
throws UnsupportedOperationException {
@@ -349,6 +360,7 @@
}
/** @throws UnsupportedOperationException since a proxy is not a Service */
+ @RequiresNoPermission
@Override
public void onServiceDisconnected(ComponentName name)
throws UnsupportedOperationException {
@@ -357,6 +369,7 @@
/** @throws UnsupportedOperationException since a proxy should use
* setInstalledAndEnabledServices*/
+ @RequiresNoPermission
@Override
public void setServiceInfo(AccessibilityServiceInfo info)
throws UnsupportedOperationException {
@@ -365,6 +378,7 @@
}
/** @throws UnsupportedOperationException since a proxy should use A11yManager#unregister */
+ @RequiresNoPermission
@Override
public void disableSelf() throws UnsupportedOperationException {
// A proxy uses A11yManager#unregister to turn itself off.
@@ -372,12 +386,14 @@
}
/** @throws UnsupportedOperationException since a proxy does not have global system access */
+ @RequiresNoPermission
@Override
public boolean performGlobalAction(int action) throws UnsupportedOperationException {
throw new UnsupportedOperationException("performGlobalAction is not supported");
}
/** @throws UnsupportedOperationException since a proxy does not need key events */
+ @RequiresNoPermission
@Override
public void setOnKeyEventResult(boolean handled, int sequence)
throws UnsupportedOperationException {
@@ -385,6 +401,7 @@
}
/** @throws UnsupportedOperationException since a proxy does not have global system access */
+ @RequiresNoPermission
@Override
public @NonNull List<AccessibilityNodeInfo.AccessibilityAction> getSystemActions()
throws UnsupportedOperationException {
@@ -393,6 +410,7 @@
/** @throws UnsupportedOperationException since a proxy does not need magnification */
@Nullable
+ @RequiresNoPermission
@Override
public MagnificationConfig getMagnificationConfig(int displayId)
throws UnsupportedOperationException {
@@ -400,30 +418,35 @@
}
/** @throws UnsupportedOperationException since a proxy does not need magnification */
+ @RequiresNoPermission
@Override
public float getMagnificationScale(int displayId) throws UnsupportedOperationException {
throw new UnsupportedOperationException("getMagnificationScale is not supported");
}
/** @throws UnsupportedOperationException since a proxy does not need magnification */
+ @RequiresNoPermission
@Override
public float getMagnificationCenterX(int displayId) throws UnsupportedOperationException {
throw new UnsupportedOperationException("getMagnificationCenterX is not supported");
}
/** @throws UnsupportedOperationException since a proxy does not need magnification */
+ @RequiresNoPermission
@Override
public float getMagnificationCenterY(int displayId) throws UnsupportedOperationException {
throw new UnsupportedOperationException("getMagnificationCenterY is not supported");
}
/** @throws UnsupportedOperationException since a proxy does not need magnification */
+ @RequiresNoPermission
@Override
public Region getMagnificationRegion(int displayId) throws UnsupportedOperationException {
throw new UnsupportedOperationException("getMagnificationRegion is not supported");
}
/** @throws UnsupportedOperationException since a proxy does not need magnification */
+ @RequiresNoPermission
@Override
public Region getCurrentMagnificationRegion(int displayId)
throws UnsupportedOperationException {
@@ -431,6 +454,7 @@
}
/** @throws UnsupportedOperationException since a proxy does not need magnification */
+ @RequiresNoPermission
@Override
public boolean resetMagnification(int displayId, boolean animate)
throws UnsupportedOperationException {
@@ -438,6 +462,7 @@
}
/** @throws UnsupportedOperationException since a proxy does not need magnification */
+ @RequiresNoPermission
@Override
public boolean resetCurrentMagnification(int displayId, boolean animate)
throws UnsupportedOperationException {
@@ -445,6 +470,7 @@
}
/** @throws UnsupportedOperationException since a proxy does not need magnification */
+ @RequiresNoPermission
@Override
public boolean setMagnificationConfig(int displayId,
@androidx.annotation.NonNull MagnificationConfig config, boolean animate)
@@ -453,6 +479,7 @@
}
/** @throws UnsupportedOperationException since a proxy does not need magnification */
+ @RequiresNoPermission
@Override
public void setMagnificationCallbackEnabled(int displayId, boolean enabled)
throws UnsupportedOperationException {
@@ -460,24 +487,28 @@
}
/** @throws UnsupportedOperationException since a proxy does not need magnification */
+ @RequiresNoPermission
@Override
public boolean isMagnificationCallbackEnabled(int displayId) {
throw new UnsupportedOperationException("isMagnificationCallbackEnabled is not supported");
}
/** @throws UnsupportedOperationException since a proxy does not need IME access*/
+ @RequiresNoPermission
@Override
public boolean setSoftKeyboardShowMode(int showMode) throws UnsupportedOperationException {
throw new UnsupportedOperationException("setSoftKeyboardShowMode is not supported");
}
/** @throws UnsupportedOperationException since a proxy does not need IME access */
+ @RequiresNoPermission
@Override
public int getSoftKeyboardShowMode() throws UnsupportedOperationException {
throw new UnsupportedOperationException("getSoftKeyboardShowMode is not supported");
}
/** @throws UnsupportedOperationException since a proxy does not need IME access */
+ @RequiresNoPermission
@Override
public void setSoftKeyboardCallbackEnabled(boolean enabled)
throws UnsupportedOperationException {
@@ -485,12 +516,14 @@
}
/** @throws UnsupportedOperationException since a proxy does not need IME access */
+ @RequiresNoPermission
@Override
public boolean switchToInputMethod(String imeId) throws UnsupportedOperationException {
throw new UnsupportedOperationException("switchToInputMethod is not supported");
}
/** @throws UnsupportedOperationException since a proxy does not need IME access */
+ @RequiresNoPermission
@Override
public int setInputMethodEnabled(String imeId, boolean enabled)
throws UnsupportedOperationException {
@@ -498,12 +531,14 @@
}
/** @throws UnsupportedOperationException since a proxy does not need access to the shortcut */
+ @RequiresNoPermission
@Override
public boolean isAccessibilityButtonAvailable() throws UnsupportedOperationException {
throw new UnsupportedOperationException("isAccessibilityButtonAvailable is not supported");
}
/** @throws UnsupportedOperationException since a proxy does not need gestures/input access */
+ @RequiresNoPermission
@Override
public void sendGesture(int sequence, ParceledListSlice gestureSteps)
throws UnsupportedOperationException {
@@ -511,6 +546,7 @@
}
/** @throws UnsupportedOperationException since a proxy does not need gestures/input access */
+ @RequiresNoPermission
@Override
public void dispatchGesture(int sequence, ParceledListSlice gestureSteps, int displayId)
throws UnsupportedOperationException {
@@ -518,6 +554,7 @@
}
/** @throws UnsupportedOperationException since a proxy does not need access to screenshots */
+ @RequiresNoPermission
@Override
public void takeScreenshot(int displayId, RemoteCallback callback)
throws UnsupportedOperationException {
@@ -525,6 +562,7 @@
}
/** @throws UnsupportedOperationException since a proxy does not need gestures/input access */
+ @RequiresNoPermission
@Override
public void setGestureDetectionPassthroughRegion(int displayId, Region region)
throws UnsupportedOperationException {
@@ -533,6 +571,7 @@
}
/** @throws UnsupportedOperationException since a proxy does not need gestures/input access */
+ @RequiresNoPermission
@Override
public void setTouchExplorationPassthroughRegion(int displayId, Region region)
throws UnsupportedOperationException {
@@ -541,6 +580,7 @@
}
/** @throws UnsupportedOperationException since a proxy does not need gestures/input access */
+ @RequiresNoPermission
@Override
public void setServiceDetectsGesturesEnabled(int displayId, boolean mode)
throws UnsupportedOperationException {
@@ -549,36 +589,42 @@
}
/** @throws UnsupportedOperationException since a proxy does not need touch input access */
+ @RequiresNoPermission
@Override
public void requestTouchExploration(int displayId) throws UnsupportedOperationException {
throw new UnsupportedOperationException("requestTouchExploration is not supported");
}
/** @throws UnsupportedOperationException since a proxy does not need touch input access */
+ @RequiresNoPermission
@Override
public void requestDragging(int displayId, int pointerId) throws UnsupportedOperationException {
throw new UnsupportedOperationException("requestDragging is not supported");
}
/** @throws UnsupportedOperationException since a proxy does not need touch input access */
+ @RequiresNoPermission
@Override
public void requestDelegating(int displayId) throws UnsupportedOperationException {
throw new UnsupportedOperationException("requestDelegating is not supported");
}
/** @throws UnsupportedOperationException since a proxy does not need touch input access */
+ @RequiresNoPermission
@Override
public void onDoubleTap(int displayId) throws UnsupportedOperationException {
throw new UnsupportedOperationException("onDoubleTap is not supported");
}
/** @throws UnsupportedOperationException since a proxy does not need touch input access */
+ @RequiresNoPermission
@Override
public void onDoubleTapAndHold(int displayId) throws UnsupportedOperationException {
throw new UnsupportedOperationException("onDoubleTapAndHold is not supported");
}
/** @throws UnsupportedOperationException since a proxy does not need touch input access */
+ @RequiresNoPermission
@Override
public void setAnimationScale(float scale) throws UnsupportedOperationException {
throw new UnsupportedOperationException("setAnimationScale is not supported");
@@ -615,6 +661,7 @@
return updated;
}
+ @PermissionManuallyEnforced
@Override
public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return;
diff --git a/services/accessibility/java/com/android/server/accessibility/UiAutomationManager.java b/services/accessibility/java/com/android/server/accessibility/UiAutomationManager.java
index aad9e24..63a183d 100644
--- a/services/accessibility/java/com/android/server/accessibility/UiAutomationManager.java
+++ b/services/accessibility/java/com/android/server/accessibility/UiAutomationManager.java
@@ -21,6 +21,8 @@
import android.accessibilityservice.AccessibilityTrace;
import android.accessibilityservice.IAccessibilityServiceClient;
import android.annotation.Nullable;
+import android.annotation.PermissionManuallyEnforced;
+import android.annotation.RequiresNoPermission;
import android.app.UiAutomation;
import android.content.ComponentName;
import android.content.Context;
@@ -242,7 +244,6 @@
}
}
- @SuppressWarnings("MissingPermissionAnnotation")
private class UiAutomationService extends AbstractAccessibilityServiceConnection {
private final Handler mMainHandler;
@@ -318,6 +319,7 @@
return true;
}
+ @PermissionManuallyEnforced
@Override
public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return;
@@ -330,31 +332,37 @@
}
// Since this isn't really an accessibility service, several methods are just stubbed here.
+ @RequiresNoPermission
@Override
public boolean setSoftKeyboardShowMode(int mode) {
return false;
}
+ @RequiresNoPermission
@Override
public int getSoftKeyboardShowMode() {
return 0;
}
+ @RequiresNoPermission
@Override
public boolean switchToInputMethod(String imeId) {
return false;
}
+ @RequiresNoPermission
@Override
public int setInputMethodEnabled(String imeId, boolean enabled) {
return AccessibilityService.SoftKeyboardController.ENABLE_IME_FAIL_UNKNOWN;
}
+ @RequiresNoPermission
@Override
public boolean isAccessibilityButtonAvailable() {
return false;
}
+ @RequiresNoPermission
@Override
public void disableSelf() {}
@@ -375,6 +383,7 @@
@Override
public void onFingerprintGesture(int gesture) {}
+ @RequiresNoPermission
@Override
public void takeScreenshot(int displayId, RemoteCallback callback) {}
}
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 522aa67..e830523 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -2292,11 +2292,32 @@
args.arg4 = requestId;
args.argi1 = widget.appWidgetId;
+ if (updateViews != null && updateViews.isLegacyListRemoteViews()) {
+ mCallbackHandler.obtainMessage(
+ CallbackHandler.MSG_NOTIFY_UPDATE_APP_WIDGET_DEFERRED,
+ args).sendToTarget();
+ return;
+ }
+
mCallbackHandler.obtainMessage(
CallbackHandler.MSG_NOTIFY_UPDATE_APP_WIDGET,
args).sendToTarget();
}
+ private void handleNotifyUpdateAppWidgetDeferred(Host host, IAppWidgetHost callbacks,
+ int appWidgetId, long requestId) {
+ try {
+ Slog.d(TAG, "Trying to notify widget update deferred for id: " + appWidgetId);
+ callbacks.updateAppWidgetDeferred(appWidgetId);
+ host.lastWidgetUpdateSequenceNo = requestId;
+ } catch (RemoteException re) {
+ synchronized (mLock) {
+ Slog.e(TAG, "Widget host dead: " + host.id, re);
+ host.callbacks = null;
+ }
+ }
+ }
+
private void handleNotifyUpdateAppWidget(Host host, IAppWidgetHost callbacks,
int appWidgetId, RemoteViews views, long requestId) {
try {
@@ -4277,6 +4298,7 @@
public static final int MSG_NOTIFY_PROVIDERS_CHANGED = 3;
public static final int MSG_NOTIFY_VIEW_DATA_CHANGED = 4;
public static final int MSG_NOTIFY_APP_WIDGET_REMOVED = 5;
+ public static final int MSG_NOTIFY_UPDATE_APP_WIDGET_DEFERRED = 6;
public CallbackHandler(Looper looper) {
super(looper, null, false);
@@ -4340,6 +4362,17 @@
handleNotifyAppWidgetViewDataChanged(host, callbacks, appWidgetId, viewId,
requestId);
} break;
+
+ case MSG_NOTIFY_UPDATE_APP_WIDGET_DEFERRED: {
+ SomeArgs args = (SomeArgs) message.obj;
+ Host host = (Host) args.arg1;
+ IAppWidgetHost callbacks = (IAppWidgetHost) args.arg2;
+ long requestId = (Long) args.arg4;
+ final int appWidgetId = args.argi1;
+ args.recycle();
+
+ handleNotifyUpdateAppWidgetDeferred(host, callbacks, appWidgetId, requestId);
+ } break;
}
}
}
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index 9701292..763879e 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -1625,13 +1625,13 @@
final class AutoFillManagerServiceStub extends IAutoFillManager.Stub {
@Override
public void addClient(IAutoFillManagerClient client, ComponentName componentName,
- int userId, IResultReceiver receiver) {
+ int userId, IResultReceiver receiver, boolean credmanRequested) {
int flags = 0;
try {
synchronized (mLock) {
final int enabledFlags =
getServiceForUserWithLocalBinderIdentityLocked(userId)
- .addClientLocked(client, componentName);
+ .addClientLocked(client, componentName, credmanRequested);
if (enabledFlags != 0) {
flags |= enabledFlags;
}
@@ -1644,7 +1644,7 @@
}
} catch (Exception ex) {
// Don't do anything, send back default flags
- Log.wtf(TAG, "addClient(): failed " + ex.toString());
+ Log.wtf(TAG, "addClient(): failed " + ex.toString(), ex);
} finally {
send(receiver, flags);
}
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index 6822229..92acce2 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -33,6 +33,7 @@
import android.annotation.Nullable;
import android.app.ActivityManagerInternal;
import android.content.ComponentName;
+import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
@@ -96,6 +97,7 @@
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
import java.util.Random;
/**
* Bridge between the {@code system_server}'s {@link AutofillManagerService} and the
@@ -293,19 +295,31 @@
* @return {@code 0} if disabled, {@code FLAG_ADD_CLIENT_ENABLED} if enabled (it might be
* OR'ed with {@code FLAG_AUGMENTED_AUTOFILL_REQUEST}).
*/
- @GuardedBy("mLock")
- int addClientLocked(IAutoFillManagerClient client, ComponentName componentName) {
- if (mClients == null) {
- mClients = new RemoteCallbackList<>();
- }
- mClients.register(client);
+ int addClientLocked(IAutoFillManagerClient client, ComponentName componentName,
+ boolean credmanRequested) {
+ synchronized (mLock) {
+ ComponentName credComponentName = getCredentialAutofillService(getContext());
- if (isEnabledLocked()) return FLAG_ADD_CLIENT_ENABLED;
+ if (!credmanRequested
+ && Objects.equals(credComponentName,
+ mInfo == null ? null : mInfo.getServiceInfo().getComponentName())) {
+ // If the service component name corresponds to cred component name, then it means
+ // no autofill provider is selected by the user. Cred Autofill Service should only
+ // be active if there is a credman request.
+ return 0;
+ }
+ if (mClients == null) {
+ mClients = new RemoteCallbackList<>();
+ }
+ mClients.register(client);
- // Check if it's enabled for augmented autofill
- if (componentName != null && isAugmentedAutofillServiceAvailableLocked()
- && isWhitelistedForAugmentedAutofillLocked(componentName)) {
- return FLAG_ADD_CLIENT_ENABLED_FOR_AUGMENTED_AUTOFILL_ONLY;
+ if (isEnabledLocked()) return FLAG_ADD_CLIENT_ENABLED;
+
+ // Check if it's enabled for augmented autofill
+ if (componentName != null && isAugmentedAutofillServiceAvailableLocked()
+ && isWhitelistedForAugmentedAutofillLocked(componentName)) {
+ return FLAG_ADD_CLIENT_ENABLED_FOR_AUGMENTED_AUTOFILL_ONLY;
+ }
}
// No flags / disabled
@@ -1486,6 +1500,22 @@
return true;
}
+ @Nullable
+ private ComponentName getCredentialAutofillService(Context context) {
+ ComponentName componentName = null;
+ String credentialManagerAutofillCompName = context.getResources().getString(
+ R.string.config_defaultCredentialManagerAutofillService);
+ if (credentialManagerAutofillCompName != null
+ && !credentialManagerAutofillCompName.isEmpty()) {
+ componentName = ComponentName.unflattenFromString(
+ credentialManagerAutofillCompName);
+ }
+ if (componentName == null) {
+ Slog.w(TAG, "Invalid CredentialAutofillService");
+ }
+ return componentName;
+ }
+
@GuardedBy("mLock")
private int getAugmentedAutofillServiceUidLocked() {
if (mRemoteAugmentedAutofillServiceInfo == null) {
diff --git a/services/autofill/java/com/android/server/autofill/SaveEventLogger.java b/services/autofill/java/com/android/server/autofill/SaveEventLogger.java
index 28e8e30..b7f12ad 100644
--- a/services/autofill/java/com/android/server/autofill/SaveEventLogger.java
+++ b/services/autofill/java/com/android/server/autofill/SaveEventLogger.java
@@ -34,6 +34,7 @@
import static com.android.server.autofill.Helper.sVerbose;
import android.annotation.IntDef;
+import android.os.SystemClock;
import android.util.Slog;
import com.android.internal.util.FrameworkStatsLog;
@@ -45,7 +46,7 @@
/**
* Helper class to log Autofill Save event stats.
*/
-public final class SaveEventLogger {
+public class SaveEventLogger {
private static final String TAG = "SaveEventLogger";
/**
@@ -112,19 +113,21 @@
public static final int NO_SAVE_REASON_WITH_DONT_SAVE_ON_FINISH_FLAG =
AUTOFILL_SAVE_EVENT_REPORTED__SAVE_UI_NOT_SHOWN_REASON__NO_SAVE_REASON_WITH_DONT_SAVE_ON_FINISH_FLAG;
+ public static final long UNINITIATED_TIMESTAMP = Long.MIN_VALUE;
+
private final int mSessionId;
private Optional<SaveEventInternal> mEventInternal;
+ private final long mSessionStartTimestamp;
- private SaveEventLogger(int sessionId) {
- mSessionId = sessionId;
- mEventInternal = Optional.of(new SaveEventInternal());
+ private SaveEventLogger(int sessionId, long sessionStartTimestamp) {
+ mSessionId = sessionId;
+ mEventInternal = Optional.of(new SaveEventInternal());
+ mSessionStartTimestamp = sessionStartTimestamp;
}
- /**
- * A factory constructor to create FillRequestEventLogger.
- */
- public static SaveEventLogger forSessionId(int sessionId) {
- return new SaveEventLogger(sessionId);
+ /** A factory constructor to create FillRequestEventLogger. */
+ public static SaveEventLogger forSessionId(int sessionId, long sessionStartTimestamp) {
+ return new SaveEventLogger(sessionId, sessionStartTimestamp);
}
/**
@@ -225,6 +228,13 @@
}
/**
+ * Returns timestamp (relative to mSessionStartTimestamp)
+ */
+ private long getElapsedTime() {
+ return SystemClock.elapsedRealtime() - mSessionStartTimestamp;
+ }
+
+ /**
* Set latency_save_ui_display_millis as long as mEventInternal presents.
*/
public void maybeSetLatencySaveUiDisplayMillis(long timestamp) {
@@ -233,6 +243,11 @@
});
}
+ /** Set latency_save_ui_display_millis as long as mEventInternal presents. */
+ public void maybeSetLatencySaveUiDisplayMillis() {
+ maybeSetLatencySaveUiDisplayMillis(getElapsedTime());
+ }
+
/**
* Set latency_save_request_millis as long as mEventInternal presents.
*/
@@ -242,6 +257,11 @@
});
}
+ /** Set latency_save_request_millis as long as mEventInternal presents. */
+ public void maybeSetLatencySaveRequestMillis() {
+ maybeSetLatencySaveRequestMillis(getElapsedTime());
+ }
+
/**
* Set latency_save_finish_millis as long as mEventInternal presents.
*/
@@ -251,6 +271,11 @@
});
}
+ /** Set latency_save_finish_millis as long as mEventInternal presents. */
+ public void maybeSetLatencySaveFinishMillis() {
+ maybeSetLatencySaveFinishMillis(getElapsedTime());
+ }
+
/**
* Set is_framework_created_save_info as long as mEventInternal presents.
*/
@@ -261,6 +286,16 @@
}
/**
+ * Set autofill_service_uid as long as mEventInternal presents.
+ */
+ public void maybeSetAutofillServiceUid(int uid) {
+ mEventInternal.ifPresent(
+ event -> {
+ event.mServiceUid = uid;
+ });
+ }
+
+ /**
* Log an AUTOFILL_SAVE_EVENT_REPORTED event.
*/
public void logAndEndEvent() {
@@ -287,7 +322,8 @@
+ " mLatencySaveUiDisplayMillis=" + event.mLatencySaveUiDisplayMillis
+ " mLatencySaveRequestMillis=" + event.mLatencySaveRequestMillis
+ " mLatencySaveFinishMillis=" + event.mLatencySaveFinishMillis
- + " mIsFrameworkCreatedSaveInfo=" + event.mIsFrameworkCreatedSaveInfo);
+ + " mIsFrameworkCreatedSaveInfo=" + event.mIsFrameworkCreatedSaveInfo
+ + " mServiceUid=" + event.mServiceUid);
}
FrameworkStatsLog.write(
AUTOFILL_SAVE_EVENT_REPORTED,
@@ -306,7 +342,8 @@
event.mLatencySaveUiDisplayMillis,
event.mLatencySaveRequestMillis,
event.mLatencySaveFinishMillis,
- event.mIsFrameworkCreatedSaveInfo);
+ event.mIsFrameworkCreatedSaveInfo,
+ event.mServiceUid);
mEventInternal = Optional.empty();
}
@@ -322,11 +359,11 @@
boolean mCancelButtonClicked = false;
boolean mDialogDismissed = false;
boolean mIsSaved = false;
- long mLatencySaveUiDisplayMillis = 0;
- long mLatencySaveRequestMillis = 0;
- long mLatencySaveFinishMillis = 0;
+ long mLatencySaveUiDisplayMillis = UNINITIATED_TIMESTAMP;
+ long mLatencySaveRequestMillis = UNINITIATED_TIMESTAMP;
+ long mLatencySaveFinishMillis = UNINITIATED_TIMESTAMP;
boolean mIsFrameworkCreatedSaveInfo = false;
-
+ int mServiceUid = -1;
SaveEventInternal() {
}
}
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index cd1ef88..8b13c4b7 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -1336,8 +1336,11 @@
mPresentationStatsEventLogger.maybeSetIsCredentialRequest(isCredmanRequested);
mPresentationStatsEventLogger.maybeSetFieldClassificationRequestId(
mFieldClassificationIdSnapshot);
+ mPresentationStatsEventLogger.maybeSetAutofillServiceUid(getAutofillServiceUid());
mFillRequestEventLogger.maybeSetRequestId(requestId);
mFillRequestEventLogger.maybeSetAutofillServiceUid(getAutofillServiceUid());
+ mSaveEventLogger.maybeSetAutofillServiceUid(getAutofillServiceUid());
+ mSessionCommittedEventLogger.maybeSetAutofillServiceUid(getAutofillServiceUid());
if (mSessionFlags.mInlineSupportedByService) {
mFillRequestEventLogger.maybeSetInlineSuggestionHostUid(mContext, userId);
}
@@ -1493,10 +1496,16 @@
mCredentialAutofillService = getCredentialAutofillService(context);
- ComponentName primaryServiceComponentName, secondaryServiceComponentName;
+ ComponentName primaryServiceComponentName, secondaryServiceComponentName = null;
if (isPrimaryCredential) {
primaryServiceComponentName = mCredentialAutofillService;
- secondaryServiceComponentName = serviceComponentName;
+ if (serviceComponentName != null
+ && !serviceComponentName.equals(mCredentialAutofillService)) {
+ // if service component name is credential autofill service, no need to initialize
+ // secondary provider. This happens if the user sets non-autofill provider as
+ // password provider.
+ secondaryServiceComponentName = serviceComponentName;
+ }
} else {
primaryServiceComponentName = serviceComponentName;
secondaryServiceComponentName = mCredentialAutofillService;
@@ -1531,7 +1540,7 @@
mFillResponseEventLogger = FillResponseEventLogger.forSessionId(sessionId);
mSessionCommittedEventLogger = SessionCommittedEventLogger.forSessionId(sessionId);
mSessionCommittedEventLogger.maybeSetComponentPackageUid(uid);
- mSaveEventLogger = SaveEventLogger.forSessionId(sessionId);
+ mSaveEventLogger = SaveEventLogger.forSessionId(sessionId, mLatencyBaseTime);
mIsPrimaryCredential = isPrimaryCredential;
mIgnoreViewStateResetToEmpty = AutofillFeatureFlags.shouldIgnoreViewStateResetToEmpty();
@@ -2440,9 +2449,7 @@
mSessionFlags.mShowingSaveUi = false;
// Log onSaveRequest result.
mSaveEventLogger.maybeSetIsSaved(true);
- final long saveRequestFinishTimestamp =
- SystemClock.elapsedRealtime() - mLatencyBaseTime;
- mSaveEventLogger.maybeSetLatencySaveFinishMillis(saveRequestFinishTimestamp);
+ mSaveEventLogger.maybeSetLatencySaveFinishMillis();
mSaveEventLogger.logAndEndEvent();
if (mDestroyed) {
Slog.w(TAG, "Call to Session#onSaveRequestSuccess() rejected - session: "
@@ -2473,9 +2480,7 @@
synchronized (mLock) {
mSessionFlags.mShowingSaveUi = false;
// Log onSaveRequest result.
- final long saveRequestFinishTimestamp =
- SystemClock.elapsedRealtime() - mLatencyBaseTime;
- mSaveEventLogger.maybeSetLatencySaveFinishMillis(saveRequestFinishTimestamp);
+ mSaveEventLogger.maybeSetLatencySaveFinishMillis();
mSaveEventLogger.logAndEndEvent();
if (mDestroyed) {
Slog.w(TAG, "Call to Session#onSaveRequestFailure() rejected - session: "
@@ -2621,8 +2626,7 @@
return;
}
}
- final long saveRequestStartTimestamp = SystemClock.elapsedRealtime() - mLatencyBaseTime;
- mSaveEventLogger.maybeSetLatencySaveRequestMillis(saveRequestStartTimestamp);
+ mSaveEventLogger.maybeSetLatencySaveRequestMillis();
mHandler.sendMessage(obtainMessage(
AutofillManagerServiceImpl::handleSessionSave,
mService, this));
@@ -3931,13 +3935,10 @@
return new SaveResult(/* logSaveShown= */ false, /* removeSession= */ true,
Event.NO_SAVE_UI_REASON_NONE);
}
- final long saveUiDisplayStartTimestamp = SystemClock.elapsedRealtime();
getUiForShowing().showSaveUi(serviceLabel, serviceIcon,
mService.getServicePackageName(), saveInfo, this,
mComponentName, this, mContext, mPendingSaveUi, isUpdate, mCompatMode,
response.getShowSaveDialogIcon(), mSaveEventLogger);
- mSaveEventLogger.maybeSetLatencySaveUiDisplayMillis(
- SystemClock.elapsedRealtime()- saveUiDisplayStartTimestamp);
if (client != null) {
try {
client.setSaveUiState(id, true);
diff --git a/services/autofill/java/com/android/server/autofill/SessionCommittedEventLogger.java b/services/autofill/java/com/android/server/autofill/SessionCommittedEventLogger.java
index cd37073..1be8548 100644
--- a/services/autofill/java/com/android/server/autofill/SessionCommittedEventLogger.java
+++ b/services/autofill/java/com/android/server/autofill/SessionCommittedEventLogger.java
@@ -17,21 +17,15 @@
package com.android.server.autofill;
import static android.view.autofill.AutofillManager.COMMIT_REASON_UNKNOWN;
+
import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_SESSION_COMMITTED;
import static com.android.server.autofill.Helper.sVerbose;
-import android.annotation.IntDef;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.provider.Settings;
-import android.text.TextUtils;
import android.util.Slog;
import android.view.autofill.AutofillManager.AutofillCommitReason;
+
import com.android.internal.util.FrameworkStatsLog;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
import java.util.Optional;
/**
@@ -91,6 +85,14 @@
});
}
+ /** Set autofill_service_uid as long as mEventInternal presents. */
+ public void maybeSetAutofillServiceUid(int uid) {
+ mEventInternal.ifPresent(
+ event -> {
+ event.mServiceUid = uid;
+ });
+ }
+
/**
* Log an AUTOFILL_SESSION_COMMITTED event.
*/
@@ -106,7 +108,8 @@
+ " mComponentPackageUid=" + event.mComponentPackageUid
+ " mRequestCount=" + event.mRequestCount
+ " mCommitReason=" + event.mCommitReason
- + " mSessionDurationMillis=" + event.mSessionDurationMillis);
+ + " mSessionDurationMillis=" + event.mSessionDurationMillis
+ + " mServiceUid=" + event.mServiceUid);
}
FrameworkStatsLog.write(
AUTOFILL_SESSION_COMMITTED,
@@ -114,7 +117,8 @@
event.mComponentPackageUid,
event.mRequestCount,
event.mCommitReason,
- event.mSessionDurationMillis);
+ event.mSessionDurationMillis,
+ event.mServiceUid);
mEventInternal = Optional.empty();
}
@@ -123,6 +127,7 @@
int mRequestCount = 0;
int mCommitReason = COMMIT_REASON_UNKNOWN;
long mSessionDurationMillis = 0;
+ int mServiceUid = -1;
SessionCommittedEventInternal() {
}
diff --git a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
index 602855d..3b9c54f 100644
--- a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
+++ b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
@@ -413,6 +413,8 @@
callback.startIntentSender(intentSender, intent);
}
}, mUiModeMgr.isNightMode(), isUpdate, compatMode, showServiceIcon);
+
+ mSaveEventLogger.maybeSetLatencySaveUiDisplayMillis();
});
}
diff --git a/services/companion/java/com/android/server/companion/virtual/camera/VirtualCameraController.java b/services/companion/java/com/android/server/companion/virtual/camera/VirtualCameraController.java
index 4547bd6..743086e 100644
--- a/services/companion/java/com/android/server/companion/virtual/camera/VirtualCameraController.java
+++ b/services/companion/java/com/android/server/companion/virtual/camera/VirtualCameraController.java
@@ -187,9 +187,9 @@
fout.println(indent + "VirtualCameraController:");
indent += indent;
synchronized (mCameras) {
- fout.printf("%sRegistered cameras:%d%n\n", indent, mCameras.size());
+ fout.println(indent + "Registered cameras: " + mCameras.size());
for (CameraDescriptor descriptor : mCameras.values()) {
- fout.printf("%s token: %s\n", indent, descriptor.mConfig);
+ fout.println(indent + " token: " + descriptor.mConfig);
}
}
}
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 8ee560b..3ff0504 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -242,6 +242,7 @@
"com.android.sysprop.watchdog",
"securebox",
"apache-commons-math",
+ "battery_saver_flag_lib",
"notification_flags_lib",
"power_hint_flags_lib",
"biometrics_flags_lib",
diff --git a/services/core/java/com/android/server/SensitiveContentProtectionManagerService.java b/services/core/java/com/android/server/SensitiveContentProtectionManagerService.java
index 64bca33..04edb57 100644
--- a/services/core/java/com/android/server/SensitiveContentProtectionManagerService.java
+++ b/services/core/java/com/android/server/SensitiveContentProtectionManagerService.java
@@ -27,6 +27,7 @@
import static com.android.internal.util.FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__STATE__START;
import static com.android.internal.util.FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__STATE__STOP;
import static com.android.internal.util.FrameworkStatsLog.SENSITIVE_NOTIFICATION_APP_PROTECTION_SESSION;
+import static com.android.server.wm.WindowManagerInternal.OnWindowRemovedListener;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -210,6 +211,12 @@
}
};
+ private final OnWindowRemovedListener mOnWindowRemovedListener = token -> {
+ synchronized (mSensitiveContentProtectionLock) {
+ mPackagesShowingSensitiveContent.removeIf(pkgInfo -> pkgInfo.getWindowToken() == token);
+ }
+ };
+
public SensitiveContentProtectionManagerService(@NonNull Context context) {
super(context);
if (sensitiveNotificationAppProtection()) {
@@ -265,6 +272,10 @@
// Intra-process call, should never happen.
}
}
+
+ if (sensitiveContentAppProtection()) {
+ mWindowManager.registerOnWindowRemovedListener(mOnWindowRemovedListener);
+ }
}
/** Cleanup any callbacks and listeners */
diff --git a/services/core/java/com/android/server/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java
index 7acca19..e2b6bd6 100644
--- a/services/core/java/com/android/server/VcnManagementService.java
+++ b/services/core/java/com/android/server/VcnManagementService.java
@@ -36,6 +36,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SuppressLint;
import android.app.AppOpsManager;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -47,6 +48,7 @@
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
+import android.net.vcn.Flags;
import android.net.vcn.IVcnManagementService;
import android.net.vcn.IVcnStatusCallback;
import android.net.vcn.IVcnUnderlyingNetworkPolicyListener;
@@ -68,6 +70,7 @@
import android.os.RemoteException;
import android.os.ServiceSpecificException;
import android.os.UserHandle;
+import android.os.UserManager;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
@@ -431,6 +434,8 @@
mTelephonySubscriptionTracker.register();
}
+ // The system server automatically has the required permissions for #getMainUser()
+ @SuppressLint("AndroidFrameworkRequiresPermission")
private void enforcePrimaryUser() {
final int uid = mDeps.getBinderCallingUid();
if (uid == Process.SYSTEM_UID) {
@@ -438,7 +443,20 @@
"Calling identity was System Server. Was Binder calling identity cleared?");
}
- if (!UserHandle.getUserHandleForUid(uid).isSystem()) {
+ final UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
+
+ if (Flags.enforceMainUser()) {
+ final UserManager userManager = mContext.getSystemService(UserManager.class);
+
+ Binder.withCleanCallingIdentity(
+ () -> {
+ if (!Objects.equals(userManager.getMainUser(), userHandle)) {
+ throw new SecurityException(
+ "VcnManagementService can only be used by callers running as"
+ + " the main user");
+ }
+ });
+ } else if (!userHandle.isSystem()) {
throw new SecurityException(
"VcnManagementService can only be used by callers running as the primary user");
}
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index ec0d897..4ca9e33 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -507,6 +507,18 @@
*/
final SparseArray<SparseArray<TimeLimitedFgsInfo>> mTimeLimitedFgsInfo = new SparseArray<>();
+ /**
+ * Foreground services of certain types will now have a time limit. If the foreground service
+ * of the offending type is not stopped within the allocated time limit, it will receive a
+ * callback via {@link Service#onTimeout(int, int)} and it must then be stopped within a few
+ * seconds. If an app fails to do so, it will be declared an ANR.
+ *
+ * @see Service#onTimeout(int, int) onTimeout callback for additional details
+ */
+ @ChangeId
+ @EnabledSince(targetSdkVersion = VERSION_CODES.VANILLA_ICE_CREAM)
+ static final long FGS_INTRODUCE_TIME_LIMITS = 317799821L;
+
// allowlisted packageName.
ArraySet<String> mAllowListWhileInUsePermissionInFgs = new ArraySet<>();
@@ -2396,11 +2408,16 @@
// "if (r.mAllowStartForeground == REASON_DENIED...)" block below.
}
}
- } else if (getTimeLimitedFgsType(foregroundServiceType)
- != ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE) {
+ } else if (CompatChanges.isChangeEnabled(
+ FGS_INTRODUCE_TIME_LIMITS, r.appInfo.uid)
+ && android.app.Flags.introduceNewServiceOntimeoutCallback()
+ && getTimeLimitedFgsType(foregroundServiceType)
+ != ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE) {
// Calling startForeground on a FGS type which has a time limit will only be
// allowed if the app is in a state where it can normally start another FGS
- // and it hasn't hit the time limit for that type in the past 24hrs.
+ // and it hasn't hit its time limit in the past 24hrs, or it has been in the
+ // foreground after it hit its time limit, or it is currently in the
+ // TOP (or better) proc state.
// See if the app could start an FGS or not.
r.clearFgsAllowStart();
@@ -2426,11 +2443,13 @@
SystemClock.elapsedRealtime() - (24 * 60 * 60 * 1000));
final long lastTimeOutAt = fgsTypeInfo.getTimeLimitExceededAt();
if (fgsTypeInfo.getFirstFgsStartRealtime() < before24Hr
+ || r.app.mState.getCurProcState() <= PROCESS_STATE_TOP
|| (lastTimeOutAt != Long.MIN_VALUE
&& r.app.mState.getLastTopTime() > lastTimeOutAt)) {
// Reset the time limit info for this fgs type if it has been
- // more than 24hrs since the first fgs start or if the app was
- // in the TOP state after time limit was exhausted.
+ // more than 24hrs since the first fgs start or if the app is
+ // currently in the TOP state or was in the TOP state after
+ // the time limit was exhausted previously.
fgsTypeInfo.reset();
} else if (lastTimeOutAt > 0) {
// Time limit was exhausted within the past 24 hours and the app
@@ -2686,7 +2705,10 @@
mAm.notifyPackageUse(r.serviceInfo.packageName,
PackageManager.NOTIFY_PACKAGE_USE_FOREGROUND_SERVICE);
- maybeUpdateFgsTrackingLocked(r, previousFgsType);
+ if (CompatChanges.isChangeEnabled(FGS_INTRODUCE_TIME_LIMITS, r.appInfo.uid)
+ && android.app.Flags.introduceNewServiceOntimeoutCallback()) {
+ maybeUpdateFgsTrackingLocked(r, previousFgsType);
+ }
} else {
if (DEBUG_FOREGROUND_SERVICE) {
Slog.d(TAG, "Suppressing startForeground() for FAS " + r);
@@ -3907,10 +3929,8 @@
Slog.w(TAG_SERVICE, "Exception from scheduleTimeoutServiceForType: " + e);
}
- if (android.app.Flags.introduceNewServiceOntimeoutCallback()) {
- // ANR the service after giving the service some time to clean up.
- mFGSAnrTimer.start(sr, mAm.mConstants.mFgsAnrExtraWaitDuration);
- }
+ // ANR the service after giving the service some time to clean up.
+ mFGSAnrTimer.start(sr, mAm.mConstants.mFgsAnrExtraWaitDuration);
}
}
@@ -3930,7 +3950,9 @@
Slog.e(TAG_SERVICE, "FGS ANR'ed: " + sr);
traceInstant("FGS ANR: ", sr);
- mAm.appNotResponding(sr.app, tr);
+ if (sr.app != null) {
+ mAm.appNotResponding(sr.app, tr);
+ }
// TODO: Can we close the ANR dialog here, if it's still shown? Currently, the ANR
// dialog really doesn't remember the "cause" (especially if there have been multiple
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 1b59c18..00c2df6 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -4342,6 +4342,7 @@
mServices.bringDownDisabledPackageServicesLocked(
packageName, null, userId, false, true, true);
+ mServices.onUidRemovedLocked(uid);
if (mBooted) {
mAtmInternal.resumeTopActivities(true);
@@ -4372,9 +4373,10 @@
Slog.w(TAG, "Can't force stop all processes of all users, that is insane!");
}
+ final int uid = getPackageManagerInternal().getPackageUid(packageName,
+ MATCH_DEBUG_TRIAGED_MISSING | MATCH_ANY_USER, UserHandle.USER_SYSTEM);
if (appId < 0 && packageName != null) {
- appId = UserHandle.getAppId(getPackageManagerInternal().getPackageUid(packageName,
- MATCH_DEBUG_TRIAGED_MISSING | MATCH_ANY_USER, UserHandle.USER_SYSTEM));
+ appId = UserHandle.getAppId(uid);
}
boolean didSomething;
@@ -4418,6 +4420,7 @@
}
didSomething = true;
}
+ mServices.onUidRemovedLocked(uid);
if (packageName == null) {
// Remove all sticky broadcasts from this user.
@@ -4778,7 +4781,7 @@
checkTime(startTime, "attachApplicationLocked: immediately before bindApplication");
bindApplicationTimeMillis = SystemClock.uptimeMillis();
- bindApplicationTimeNanos = SystemClock.elapsedRealtimeNanos();
+ bindApplicationTimeNanos = SystemClock.uptimeNanos();
mAtmInternal.preBindApplication(app.getWindowProcessController());
final ActiveInstrumentation instr2 = app.getActiveInstrumentation();
if (mPlatformCompat != null) {
@@ -4848,7 +4851,8 @@
app.setBindApplicationTime(bindApplicationTimeMillis);
mProcessList.getAppStartInfoTracker()
- .reportBindApplicationTimeNanos(app, bindApplicationTimeNanos);
+ .addTimestampToStart(app, bindApplicationTimeNanos,
+ ApplicationStartInfo.START_TIMESTAMP_BIND_APPLICATION);
// Make app active after binding application or client may be running requests (e.g
// starting activities) before it is ready.
@@ -14314,7 +14318,7 @@
// activity manager to announce its creation.
public boolean bindBackupAgent(String packageName, int backupMode, int targetUserId,
@BackupDestination int backupDestination) {
- long startTimeNs = SystemClock.elapsedRealtimeNanos();
+ long startTimeNs = SystemClock.uptimeNanos();
if (DEBUG_BACKUP) {
Slog.v(TAG, "bindBackupAgent: app=" + packageName + " mode=" + backupMode
+ " targetUserId=" + targetUserId + " callingUid = " + Binder.getCallingUid()
@@ -19413,7 +19417,6 @@
// If the process is known as top app, set a hint so when the process is
// started, the top priority can be applied immediately to avoid cpu being
// preempted by other processes before attaching the process of top app.
- final long startTimeNs = SystemClock.elapsedRealtimeNanos();
HostingRecord hostingRecord =
new HostingRecord(hostingType, hostingName, isTop);
ProcessRecord rec = getProcessRecordLocked(processName, info.uid);
@@ -19950,6 +19953,20 @@
return !ActivityManagerService.this.mThemeOverlayReadyUsers.contains(userId);
}
}
+
+ @Override
+ public void addStartInfoTimestamp(int key, long timestampNs, int uid, int pid,
+ int userId) {
+ // For the simplification, we don't support USER_ALL nor USER_CURRENT here.
+ if (userId == UserHandle.USER_ALL || userId == UserHandle.USER_CURRENT) {
+ throw new IllegalArgumentException("Unsupported userId");
+ }
+
+ mUserController.handleIncomingUser(pid, uid, userId, true,
+ ALLOW_NON_FULL, "addStartInfoTimestampSystem", null);
+
+ addStartInfoTimestampInternal(key, timestampNs, userId, uid);
+ }
}
long inputDispatchingTimedOut(int pid, final boolean aboveSystem, TimeoutRecord timeoutRecord) {
@@ -20266,7 +20283,7 @@
final int userId = UserHandle.getCallingUserId();
final long callingId = Binder.clearCallingIdentity();
try {
- if (uid == -1) {
+ if (uid == INVALID_UID) {
uid = mPackageManagerInt.getPackageUid(packageName, 0, userId);
}
mAppRestrictionController.noteAppRestrictionEnabled(packageName, uid, restrictionType,
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 5af9424..3cea014 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -4552,10 +4552,9 @@
pw.println(" 1: crop_windows");
pw.println(" 2: resizeable");
pw.println(" 3: resizeable_and_pipable");
- pw.println(" resize <TASK_ID> <LEFT,TOP,RIGHT,BOTTOM>");
- pw.println(" Makes sure <TASK_ID> is in a stack with the specified bounds.");
- pw.println(" Forces the task to be resizeable and creates a stack if no existing stack");
- pw.println(" has the specified bounds.");
+ pw.println(" resize <TASK_ID> <LEFT> <TOP> <RIGHT> <BOTTOM>");
+ pw.println(" The task is resized only if it is in multi-window windowing");
+ pw.println(" mode or freeform windowing mode.");
pw.println(" update-appinfo <USER_ID> <PACKAGE_NAME> [<PACKAGE_NAME>...]");
pw.println(" Update the ApplicationInfo objects of the listed packages for <USER_ID>");
pw.println(" without restarting any processes.");
diff --git a/services/core/java/com/android/server/am/AppRestrictionController.java b/services/core/java/com/android/server/am/AppRestrictionController.java
index c5cad14..f5f1928 100644
--- a/services/core/java/com/android/server/am/AppRestrictionController.java
+++ b/services/core/java/com/android/server/am/AppRestrictionController.java
@@ -2387,8 +2387,8 @@
// Limit the length of the free-form subReason string
if (subReason != null && subReason.length() > RESTRICTION_SUBREASON_MAX_LENGTH) {
+ Slog.e(TAG, "subReason is too long, truncating " + subReason);
subReason = subReason.substring(0, RESTRICTION_SUBREASON_MAX_LENGTH);
- Slog.e(TAG, "Subreason is too long, truncating: " + subReason);
}
// Log the restriction reason
diff --git a/services/core/java/com/android/server/am/AppStartInfoTracker.java b/services/core/java/com/android/server/am/AppStartInfoTracker.java
index 376f654..79a8518 100644
--- a/services/core/java/com/android/server/am/AppStartInfoTracker.java
+++ b/services/core/java/com/android/server/am/AppStartInfoTracker.java
@@ -74,6 +74,7 @@
/** A class to manage all the {@link android.app.ApplicationStartInfo} records. */
public final class AppStartInfoTracker {
private static final String TAG = TAG_WITH_CLASS_NAME ? "AppStartInfoTracker" : TAG_AM;
+ private static final boolean DEBUG = false;
/** Interval of persisting the app start info to persistent storage. */
private static final long APP_START_INFO_PERSIST_INTERVAL = TimeUnit.MINUTES.toMillis(30);
@@ -293,9 +294,11 @@
mInProgRecords.removeAt(index);
return;
}
- info.setStartupState(ApplicationStartInfo.STARTUP_STATE_FIRST_FRAME_DRAWN);
info.setLaunchMode(launchMode);
- checkCompletenessAndCallback(info);
+ if (!android.app.Flags.appStartInfoTimestamps()) {
+ info.setStartupState(ApplicationStartInfo.STARTUP_STATE_FIRST_FRAME_DRAWN);
+ checkCompletenessAndCallback(info);
+ }
}
}
@@ -423,14 +426,6 @@
}
}
- void reportApplicationOnCreateTimeNanos(ProcessRecord app, long timeNs) {
- if (!mEnabled) {
- return;
- }
- addTimestampToStart(app, timeNs,
- ApplicationStartInfo.START_TIMESTAMP_APPLICATION_ONCREATE);
- }
-
/**
* Helper functions for monitoring shell command.
* > adb shell am start-info-detailed-monitoring [package-name]
@@ -465,45 +460,22 @@
}
}
- /** Report a bind application timestamp to add to {@link ApplicationStartInfo}. */
- public void reportBindApplicationTimeNanos(ProcessRecord app, long timeNs) {
- addTimestampToStart(app, timeNs,
- ApplicationStartInfo.START_TIMESTAMP_BIND_APPLICATION);
- }
-
- void reportFirstFrameTimeNanos(ProcessRecord app, long timeNs) {
- if (!mEnabled) {
- return;
- }
- addTimestampToStart(app, timeNs,
- ApplicationStartInfo.START_TIMESTAMP_FIRST_FRAME);
- }
-
- void reportFullyDrawnTimeNanos(ProcessRecord app, long timeNs) {
- if (!mEnabled) {
- return;
- }
- addTimestampToStart(app, timeNs,
- ApplicationStartInfo.START_TIMESTAMP_FULLY_DRAWN);
- }
-
- void reportFullyDrawnTimeNanos(String processName, int uid, long timeNs) {
- if (!mEnabled) {
- return;
- }
- addTimestampToStart(processName, uid, timeNs,
- ApplicationStartInfo.START_TIMESTAMP_FULLY_DRAWN);
- }
-
- private void addTimestampToStart(ProcessRecord app, long timeNs, int key) {
+ void addTimestampToStart(ProcessRecord app, long timeNs, int key) {
addTimestampToStart(app.info.packageName, app.uid, timeNs, key);
}
void addTimestampToStart(String packageName, int uid, long timeNs, int key) {
+ if (!mEnabled) {
+ return;
+ }
synchronized (mLock) {
AppStartInfoContainer container = mData.get(packageName, uid);
if (container == null) {
// Record was not created, discard new data.
+ if (DEBUG) {
+ Slog.d(TAG, "No container found for package=" + packageName + " and uid=" + uid
+ + ". Discarding timestamp key=" + key + " val=" + timeNs);
+ }
return;
}
container.addTimestampToStartLocked(key, timeNs);
@@ -534,9 +506,9 @@
}
/**
- * Called whenever data is added to a {@link ApplicationStartInfo} object. Checks for
- * completeness and triggers callback if a callback has been registered and the object
- * is complete.
+ * Called whenever a potentially final piece of data is added to a {@link ApplicationStartInfo}
+ * object. Checks for completeness and triggers callback if a callback has been registered and
+ * the object is complete.
*/
private void checkCompletenessAndCallback(ApplicationStartInfo startInfo) {
synchronized (mLock) {
@@ -1119,13 +1091,46 @@
Long.compare(getStartTimestamp(b), getStartTimestamp(a)));
}
+ /**
+ * Add the provided key/timestamp to the most recent start record, if it is currently
+ * accepting new timestamps.
+ *
+ * Will also update the start records startup state and trigger the completion listener when
+ * appropriate.
+ */
@GuardedBy("mLock")
void addTimestampToStartLocked(int key, long timestampNs) {
- int index = mInfos.size() - 1;
- int startupState = mInfos.get(index).getStartupState();
- if (startupState == ApplicationStartInfo.STARTUP_STATE_STARTED
- || key == ApplicationStartInfo.START_TIMESTAMP_FULLY_DRAWN) {
- mInfos.get(index).addStartupTimestamp(key, timestampNs);
+ if (mInfos.isEmpty()) {
+ if (DEBUG) Slog.d(TAG, "No records to add to.");
+ return;
+ }
+
+ // Records are sorted newest to oldest, grab record at index 0.
+ ApplicationStartInfo startInfo = mInfos.get(0);
+ int startupState = startInfo.getStartupState();
+
+ // If startup state is error then don't accept any further timestamps.
+ if (startupState == ApplicationStartInfo.STARTUP_STATE_ERROR) {
+ if (DEBUG) Slog.d(TAG, "Startup state is error, not accepting new timestamps.");
+ return;
+ }
+
+ // If startup state is first frame drawn then only accept fully drawn timestamp.
+ if (startupState == ApplicationStartInfo.STARTUP_STATE_FIRST_FRAME_DRAWN
+ && key != ApplicationStartInfo.START_TIMESTAMP_FULLY_DRAWN) {
+ if (DEBUG) {
+ Slog.d(TAG, "Startup state is first frame drawn and timestamp is not fully "
+ + "drawn, not accepting new timestamps.");
+ }
+ return;
+ }
+
+ startInfo.addStartupTimestamp(key, timestampNs);
+
+ if (key == ApplicationStartInfo.START_TIMESTAMP_FIRST_FRAME
+ && android.app.Flags.appStartInfoTimestamps()) {
+ startInfo.setStartupState(ApplicationStartInfo.STARTUP_STATE_FIRST_FRAME_DRAWN);
+ checkCompletenessAndCallback(startInfo);
}
}
diff --git a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
index 4425a38..1379c9b 100644
--- a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
+++ b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
@@ -1021,6 +1021,7 @@
final boolean allowWhileBooting = (r.intent.getFlags()
& Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0;
+ long startTimeNs = SystemClock.uptimeNanos();
if (DEBUG_BROADCAST) logv("Scheduling " + r + " to cold " + queue);
queue.app = mService.startProcessLocked(queue.processName, info, true, intentFlags,
hostingRecord, zygotePolicyFlags, allowWhileBooting, false);
@@ -1032,8 +1033,7 @@
}
// TODO: b/335420031 - cache receiver intent to avoid multiple calls to getReceiverIntent.
mService.mProcessList.getAppStartInfoTracker().handleProcessBroadcastStart(
- SystemClock.elapsedRealtimeNanos(), queue.app, r.getReceiverIntent(receiver),
- r.alarm /* isAlarm */);
+ startTimeNs, queue.app, r.getReceiverIntent(receiver), r.alarm /* isAlarm */);
return false;
}
diff --git a/services/core/java/com/android/server/am/ContentProviderHelper.java b/services/core/java/com/android/server/am/ContentProviderHelper.java
index 28fd197..a8b9e43 100644
--- a/services/core/java/com/android/server/am/ContentProviderHelper.java
+++ b/services/core/java/com/android/server/am/ContentProviderHelper.java
@@ -179,7 +179,7 @@
final int expectedUserId = userId;
synchronized (mService) {
long startTime = SystemClock.uptimeMillis();
- long startElapsedTimeNs = SystemClock.elapsedRealtimeNanos();
+ long startTimeNs = SystemClock.uptimeNanos();
ProcessRecord r = null;
if (caller != null) {
@@ -587,7 +587,7 @@
firstLaunch,
0L /* TODO: stoppedDuration */);
mService.mProcessList.getAppStartInfoTracker()
- .handleProcessContentProviderStart(startElapsedTimeNs, proc);
+ .handleProcessContentProviderStart(startTimeNs, proc);
}
cpr.launchingApp = proc;
mLaunchingProviders.add(cpr);
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index a289dd1..cc6ae5c 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -2610,6 +2610,15 @@
}
}
+ // Sandbox should be able to control audio only when bound client
+ // has this capability.
+ if ((cstate.getCurCapability()
+ & PROCESS_CAPABILITY_FOREGROUND_AUDIO_CONTROL) != 0) {
+ if (app.isSdkSandbox) {
+ capability |= PROCESS_CAPABILITY_FOREGROUND_AUDIO_CONTROL;
+ }
+ }
+
if (couldRecurse && shouldSkipDueToCycle(app, cstate, procState, adj, cycleReEval)) {
return false;
}
diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
index 9b83ede..9520621 100644
--- a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
+++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
@@ -128,6 +128,7 @@
"aoc",
"app_widgets",
"arc_next",
+ "art_mainline",
"avic",
"biometrics",
"biometrics_framework",
diff --git a/services/core/java/com/android/server/apphibernation/AppHibernationService.java b/services/core/java/com/android/server/apphibernation/AppHibernationService.java
index ce41079..e066c23 100644
--- a/services/core/java/com/android/server/apphibernation/AppHibernationService.java
+++ b/services/core/java/com/android/server/apphibernation/AppHibernationService.java
@@ -572,12 +572,8 @@
packageName, uid, ActivityManager.RESTRICTION_LEVEL_FORCE_STOPPED,
true, ActivityManager.RESTRICTION_REASON_DORMANT, null,
/* TODO: fetch actual timeout - 90 days */ 90 * 24 * 60 * 60_000L);
- } else {
- mIActivityManager.noteAppRestrictionEnabled(
- packageName, uid, ActivityManager.RESTRICTION_LEVEL_FORCE_STOPPED,
- false, ActivityManager.RESTRICTION_REASON_USAGE, null,
- 0L);
}
+ // No need to log the unhibernate case as an unstop is logged already in ActivityMS
} catch (RemoteException e) {
Slog.e(TAG, "Couldn't set restriction state change");
}
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 798aaee..6308652 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -1102,6 +1102,7 @@
if (onModeChangedListeners == null) {
continue;
}
+ onModeChangedListeners = new ArraySet<>(onModeChangedListeners);
}
for (int i = 0; i < changedUids.length; i++) {
final int changedUid = changedUids[i];
@@ -6396,12 +6397,13 @@
}
private void notifyWatchersOnDefaultDevice(int code, int uid) {
- final ArraySet<OnOpModeChangedListener> modeChangedListenerSet;
+ ArraySet<OnOpModeChangedListener> modeChangedListenerSet;
synchronized (this) {
modeChangedListenerSet = mOpModeWatchers.get(code);
if (modeChangedListenerSet == null) {
return;
}
+ modeChangedListenerSet = new ArraySet<>(modeChangedListenerSet);
}
notifyOpChanged(modeChangedListenerSet, code, uid, null, PERSISTENT_DEVICE_ID_DEFAULT);
}
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index da528a2..475334c 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -274,8 +274,11 @@
}
/*package*/ void setBluetoothA2dpOn_Async(boolean on, String source) {
- mBluetoothA2dpEnabled.set(on);
- sendLMsgNoDelay(MSG_L_SET_FORCE_BT_A2DP_USE, SENDMSG_REPLACE, source);
+ boolean wasOn = mBluetoothA2dpEnabled.getAndSet(on);
+ // do not mute music if we do not anticipate a change in A2DP ON state
+ sendLMsgNoDelay(wasOn == on
+ ? MSG_L_SET_FORCE_BT_A2DP_USE_NO_MUTE : MSG_L_SET_FORCE_BT_A2DP_USE,
+ SENDMSG_REPLACE, source);
}
/**
@@ -1803,6 +1806,7 @@
onSetForceUse(msg.arg1, msg.arg2, false, (String) msg.obj);
break;
case MSG_L_SET_FORCE_BT_A2DP_USE:
+ case MSG_L_SET_FORCE_BT_A2DP_USE_NO_MUTE:
int forcedUsage = mBluetoothA2dpEnabled.get()
? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP;
onSetForceUse(AudioSystem.FOR_MEDIA, forcedUsage, true, (String) msg.obj);
@@ -2139,8 +2143,7 @@
private static final int MSG_I_UPDATE_LE_AUDIO_GROUP_ADDRESSES = 57;
private static final int MSG_L_SYNCHRONIZE_ADI_DEVICES_IN_INVENTORY = 58;
private static final int MSG_IL_UPDATED_ADI_DEVICE_STATE = 59;
-
-
+ private static final int MSG_L_SET_FORCE_BT_A2DP_USE_NO_MUTE = 60;
private static boolean isMessageHandledUnderWakelock(int msgId) {
switch(msgId) {
diff --git a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
index 28af222..d26ba48 100644
--- a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
+++ b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
@@ -26,6 +26,8 @@
import static android.media.AudioPlaybackConfiguration.PLAYER_PIID_INVALID;
import static android.media.AudioPlaybackConfiguration.PLAYER_UPDATE_MUTED;
+import static com.android.media.audio.Flags.portToPiidSimplification;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
@@ -152,6 +154,8 @@
new HashMap<Integer, AudioPlaybackConfiguration>();
@GuardedBy("mPlayerLock")
+ private final SparseIntArray mPiidToPortId = new SparseIntArray();
+ @GuardedBy("mPlayerLock")
private final SparseIntArray mPortIdToPiid = new SparseIntArray();
private final Context mContext;
@@ -369,7 +373,11 @@
sEventLogger.enqueue(new PlayerEvent(piid, event, eventValue));
if (event == AudioPlaybackConfiguration.PLAYER_UPDATE_PORT_ID) {
- mPortIdToPiid.put(eventValue, piid);
+ if (portToPiidSimplification()) {
+ mPiidToPortId.put(piid, eventValue);
+ } else {
+ mPortIdToPiid.put(eventValue, piid);
+ }
return;
} else if (event == AudioPlaybackConfiguration.PLAYER_STATE_STARTED) {
for (Integer uidInteger: mBannedUids) {
@@ -430,10 +438,20 @@
}
synchronized (mPlayerLock) {
- int piid = mPortIdToPiid.get(portId, PLAYER_PIID_INVALID);
- if (piid == PLAYER_PIID_INVALID) {
- Log.w(TAG, "No piid assigned for invalid/internal port id " + portId);
- return;
+ int piid;
+ if (portToPiidSimplification()) {
+ int idxOfPiid = mPiidToPortId.indexOfValue(portId);
+ if (idxOfPiid < 0) {
+ Log.w(TAG, "No piid assigned for invalid/internal port id " + portId);
+ return;
+ }
+ piid = mPiidToPortId.keyAt(idxOfPiid);
+ } else {
+ piid = mPortIdToPiid.get(portId, PLAYER_PIID_INVALID);
+ if (piid == PLAYER_PIID_INVALID) {
+ Log.w(TAG, "No piid assigned for invalid/internal port id " + portId);
+ return;
+ }
}
final AudioPlaybackConfiguration apc = mPlayers.get(piid);
if (apc == null) {
@@ -489,10 +507,14 @@
change = apc.handleStateEvent(AudioPlaybackConfiguration.PLAYER_STATE_RELEASED,
AudioPlaybackConfiguration.PLAYER_DEVICEID_INVALID);
- // remove all port ids mapped to the released player
- int portIdx;
- while ((portIdx = mPortIdToPiid.indexOfValue(piid)) >= 0) {
- mPortIdToPiid.removeAt(portIdx);
+ if (portToPiidSimplification()) {
+ mPiidToPortId.delete(piid);
+ } else {
+ // remove all port ids mapped to the released player
+ int portIdx;
+ while ((portIdx = mPortIdToPiid.indexOfValue(piid)) >= 0) {
+ mPortIdToPiid.removeAt(portIdx);
+ }
}
if (change && mDoNotLogPiidList.contains(piid)) {
@@ -511,10 +533,17 @@
new EventLogger.StringEvent(
"clear port id to piid map"));
synchronized (mPlayerLock) {
- if (DEBUG) {
- Log.v(TAG, "clear port id to piid map:\n" + mPortIdToPiid);
+ if (portToPiidSimplification()) {
+ if (DEBUG) {
+ Log.v(TAG, "clear piid to portId map:\n" + mPiidToPortId);
+ }
+ mPiidToPortId.clear();
+ } else {
+ if (DEBUG) {
+ Log.v(TAG, "clear port id to piid map:\n" + mPortIdToPiid);
+ }
+ mPortIdToPiid.clear();
}
- mPortIdToPiid.clear();
}
}
@@ -674,12 +703,21 @@
pw.print(" " + piid);
}
pw.println("\n");
- // portId to piid mappings:
- pw.println("\n current portId to piid map:");
- for (int i = 0; i < mPortIdToPiid.size(); ++i) {
- pw.println(
- " portId: " + mPortIdToPiid.keyAt(i) + " piid: " + mPortIdToPiid.valueAt(
- i));
+ if (portToPiidSimplification()) {
+ // portId to piid mappings:
+ pw.println("\n current piid to portId map:");
+ for (int i = 0; i < mPiidToPortId.size(); ++i) {
+ pw.println(
+ " piid: " + mPiidToPortId.keyAt(i) + " portId: "
+ + mPiidToPortId.valueAt(i));
+ }
+ } else {
+ // portId to piid mappings:
+ pw.println("\n current portId to piid map:");
+ for (int i = 0; i < mPortIdToPiid.size(); ++i) {
+ pw.println(" portId: " + mPortIdToPiid.keyAt(i) + " piid: "
+ + mPortIdToPiid.valueAt(i));
+ }
}
pw.println("\n");
// log
diff --git a/services/core/java/com/android/server/biometrics/biometrics.aconfig b/services/core/java/com/android/server/biometrics/biometrics.aconfig
index 92fd9cb..712dcee 100644
--- a/services/core/java/com/android/server/biometrics/biometrics.aconfig
+++ b/services/core/java/com/android/server/biometrics/biometrics.aconfig
@@ -14,3 +14,10 @@
description: "This flag controls whether virtual HAL is used for testing instead of TestHal "
bug: "294254230"
}
+
+flag {
+ name: "mandatory_biometrics"
+ namespace: "biometrics_framework"
+ description: "This flag controls whether LSKF fallback is removed from biometric prompt when the phone is outside trusted locations"
+ bug: "322081563"
+}
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index 9c020a7..d9c3ab8 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -181,7 +181,7 @@
private long mLightSensorEnableTime;
// The currently accepted nominal ambient light level.
- private float mAmbientLux;
+ private float mAmbientLux = INVALID_LUX;
// The last calculated ambient light level (long time window).
private float mSlowAmbientLux;
@@ -434,23 +434,23 @@
* entering doze - we disable the light sensor, invalidate the lux, but we still need to set
* the initial brightness in doze mode.
*/
- public float getAutomaticScreenBrightnessBasedOnLastObservedLux(
+ public float getAutomaticScreenBrightnessBasedOnLastUsedLux(
BrightnessEvent brightnessEvent) {
- if (mLastObservedLux == INVALID_LUX) {
+ float lastUsedLux = mAmbientLux;
+ if (lastUsedLux == INVALID_LUX) {
return PowerManager.BRIGHTNESS_INVALID_FLOAT;
}
- float brightness = mCurrentBrightnessMapper.getBrightness(mLastObservedLux,
+ float brightness = mCurrentBrightnessMapper.getBrightness(lastUsedLux,
mForegroundAppPackageName, mForegroundAppCategory);
if (shouldApplyDozeScaleFactor()) {
brightness *= mDozeScaleFactor;
}
if (brightnessEvent != null) {
- brightnessEvent.setLux(mLastObservedLux);
+ brightnessEvent.setLux(lastUsedLux);
brightnessEvent.setRecommendedBrightness(brightness);
brightnessEvent.setFlags(brightnessEvent.getFlags()
- | (mLastObservedLux == INVALID_LUX ? BrightnessEvent.FLAG_INVALID_LUX : 0)
| (shouldApplyDozeScaleFactor() ? BrightnessEvent.FLAG_DOZE_SCALE : 0));
brightnessEvent.setAutoBrightnessMode(getMode());
}
diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
index a6335e3..eeacc53 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
@@ -1268,7 +1268,7 @@
return mAmbientLightSensor;
}
- SensorData getScreenOffBrightnessSensor() {
+ public SensorData getScreenOffBrightnessSensor() {
return mScreenOffBrightnessSensor;
}
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index c5d8686..d7a7dd4 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -851,6 +851,13 @@
mHandler.postAtTime(() -> {
boolean changed = false;
+
+ if (mIsEnabled != isEnabled || mIsInTransition != isInTransition) {
+ changed = true;
+ mIsEnabled = isEnabled;
+ mIsInTransition = isInTransition;
+ }
+
if (mDisplayDevice != device) {
changed = true;
mDisplayDevice = device;
@@ -875,11 +882,6 @@
mThermalBrightnessThrottlingDataId,
mUniqueDisplayId);
}
- if (mIsEnabled != isEnabled || mIsInTransition != isInTransition) {
- changed = true;
- mIsEnabled = isEnabled;
- mIsInTransition = isInTransition;
- }
mIsDisplayInternal = isDisplayInternal;
// using local variables here, when mBrightnessThrottler is removed,
@@ -1113,29 +1115,29 @@
mBrightnessThrottler, mDisplayDeviceConfig.getAmbientHorizonShort(),
mDisplayDeviceConfig.getAmbientHorizonLong(), userLux, userNits,
mBrightnessClamperController);
- mDisplayBrightnessController.setAutomaticBrightnessController(
- mAutomaticBrightnessController);
-
- mAutomaticBrightnessStrategy
- .setAutomaticBrightnessController(mAutomaticBrightnessController);
+ mDisplayBrightnessController.setUpAutoBrightness(
+ mAutomaticBrightnessController, mSensorManager, mDisplayDeviceConfig, mHandler,
+ defaultModeBrightnessMapper, mIsEnabled, mLeadDisplayId);
mBrightnessEventRingBuffer =
new RingBuffer<>(BrightnessEvent.class, RINGBUFFER_MAX);
-
- if (mScreenOffBrightnessSensorController != null) {
- mScreenOffBrightnessSensorController.stop();
- mScreenOffBrightnessSensorController = null;
- }
- loadScreenOffBrightnessSensor();
- int[] sensorValueToLux = mDisplayDeviceConfig.getScreenOffBrightnessSensorValueToLux();
- if (mScreenOffBrightnessSensor != null && sensorValueToLux != null) {
- mScreenOffBrightnessSensorController =
- mInjector.getScreenOffBrightnessSensorController(
- mSensorManager,
- mScreenOffBrightnessSensor,
- mHandler,
- SystemClock::uptimeMillis,
- sensorValueToLux,
- defaultModeBrightnessMapper);
+ if (!mFlags.isRefactorDisplayPowerControllerEnabled()) {
+ if (mScreenOffBrightnessSensorController != null) {
+ mScreenOffBrightnessSensorController.stop();
+ mScreenOffBrightnessSensorController = null;
+ }
+ loadScreenOffBrightnessSensor();
+ int[] sensorValueToLux =
+ mDisplayDeviceConfig.getScreenOffBrightnessSensorValueToLux();
+ if (mScreenOffBrightnessSensor != null && sensorValueToLux != null) {
+ mScreenOffBrightnessSensorController =
+ mInjector.getScreenOffBrightnessSensorController(
+ mSensorManager,
+ mScreenOffBrightnessSensor,
+ mHandler,
+ SystemClock::uptimeMillis,
+ sensorValueToLux,
+ defaultModeBrightnessMapper);
+ }
}
} else {
mUseSoftwareAutoBrightnessConfig = false;
@@ -1255,7 +1257,8 @@
mPowerState = null;
}
- if (mScreenOffBrightnessSensorController != null) {
+ if (!mFlags.isRefactorDisplayPowerControllerEnabled()
+ && mScreenOffBrightnessSensorController != null) {
mScreenOffBrightnessSensorController.stop();
}
@@ -1351,15 +1354,17 @@
if (displayBrightnessState.getBrightnessEvent() != null) {
mTempBrightnessEvent.copyFrom(displayBrightnessState.getBrightnessEvent());
}
- // Set up the ScreenOff controller used when coming out of SCREEN_OFF and the ALS sensor
- // doesn't yet have a valid lux value to use with auto-brightness.
- if (mScreenOffBrightnessSensorController != null) {
- mScreenOffBrightnessSensorController
- .setLightSensorEnabled(displayBrightnessState.getShouldUseAutoBrightness()
- && mIsEnabled && (state == Display.STATE_OFF
- || (state == Display.STATE_DOZE
- && !mDisplayBrightnessController.isAllowAutoBrightnessWhileDozingConfig()))
- && mLeadDisplayId == Layout.NO_LEAD_DISPLAY);
+ if (!mFlags.isRefactorDisplayPowerControllerEnabled()) {
+ // Set up the ScreenOff controller used when coming out of SCREEN_OFF and the ALS sensor
+ // doesn't yet have a valid lux value to use with auto-brightness.
+ if (mScreenOffBrightnessSensorController != null) {
+ mScreenOffBrightnessSensorController
+ .setLightSensorEnabled(displayBrightnessState.getShouldUseAutoBrightness()
+ && mIsEnabled && (state == Display.STATE_OFF
+ || (state == Display.STATE_DOZE
+ && !mDisplayBrightnessController.isAllowAutoBrightnessWhileDozingConfig()))
+ && mLeadDisplayId == Layout.NO_LEAD_DISPLAY);
+ }
}
// Take note if the short term model was already active before applying the current
@@ -1392,15 +1397,6 @@
boolean updateScreenBrightnessSetting =
displayBrightnessState.shouldUpdateScreenBrightnessSetting();
float currentBrightnessSetting = mDisplayBrightnessController.getCurrentBrightness();
- // Apply auto-brightness.
- // All the conditions inside this if block will be moved to AutomaticBrightnessStrategy
- if (mFlags.isRefactorDisplayPowerControllerEnabled()
- && displayBrightnessState.getBrightnessReason().getReason()
- == BrightnessReason.REASON_AUTOMATIC) {
- if (mScreenOffBrightnessSensorController != null) {
- mScreenOffBrightnessSensorController.setLightSensorEnabled(false);
- }
- }
if (!mFlags.isRefactorDisplayPowerControllerEnabled()) {
// AutomaticBrightnessStrategy has higher priority than OffloadBrightnessStrategy
@@ -1452,7 +1448,7 @@
&& mAutomaticBrightnessStrategy.shouldUseAutoBrightness()) {
// Use the auto-brightness curve and the last observed lux
rawBrightnessState = mAutomaticBrightnessController
- .getAutomaticScreenBrightnessBasedOnLastObservedLux(
+ .getAutomaticScreenBrightnessBasedOnLastUsedLux(
mTempBrightnessEvent);
} else {
rawBrightnessState = getDozeBrightnessForOffload();
@@ -1473,19 +1469,23 @@
mBrightnessReasonTemp.setReason(BrightnessReason.REASON_DOZE_DEFAULT);
}
- // The ALS is not available yet - use the screen off sensor to determine the initial
- // brightness
- if (Float.isNaN(brightnessState) && mAutomaticBrightnessStrategy.isAutoBrightnessEnabled()
- && mScreenOffBrightnessSensorController != null) {
- rawBrightnessState =
- mScreenOffBrightnessSensorController.getAutomaticScreenBrightness();
- brightnessState = rawBrightnessState;
- if (BrightnessUtils.isValidBrightnessValue(brightnessState)) {
- brightnessState = clampScreenBrightness(brightnessState);
- updateScreenBrightnessSetting = mDisplayBrightnessController.getCurrentBrightness()
- != brightnessState;
- mBrightnessReasonTemp.setReason(
- BrightnessReason.REASON_SCREEN_OFF_BRIGHTNESS_SENSOR);
+ if (!mFlags.isRefactorDisplayPowerControllerEnabled()) {
+ // The ALS is not available yet - use the screen off sensor to determine the initial
+ // brightness
+ if (Float.isNaN(brightnessState)
+ && mAutomaticBrightnessStrategy.isAutoBrightnessEnabled()
+ && mScreenOffBrightnessSensorController != null) {
+ rawBrightnessState =
+ mScreenOffBrightnessSensorController.getAutomaticScreenBrightness();
+ brightnessState = rawBrightnessState;
+ if (BrightnessUtils.isValidBrightnessValue(brightnessState)) {
+ brightnessState = clampScreenBrightness(brightnessState);
+ updateScreenBrightnessSetting =
+ mDisplayBrightnessController.getCurrentBrightness()
+ != brightnessState;
+ mBrightnessReasonTemp.setReason(
+ BrightnessReason.REASON_SCREEN_OFF_BRIGHTNESS_SENSOR);
+ }
}
}
diff --git a/services/core/java/com/android/server/display/ScreenOffBrightnessSensorController.java b/services/core/java/com/android/server/display/ScreenOffBrightnessSensorController.java
index 42defac..0a884c9 100644
--- a/services/core/java/com/android/server/display/ScreenOffBrightnessSensorController.java
+++ b/services/core/java/com/android/server/display/ScreenOffBrightnessSensorController.java
@@ -25,8 +25,6 @@
import android.os.PowerManager;
import android.util.IndentingPrintWriter;
-import com.android.internal.annotations.VisibleForTesting;
-
import java.io.PrintWriter;
/**
@@ -79,7 +77,10 @@
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
- void setLightSensorEnabled(boolean enabled) {
+ /**
+ * Changes the state of the associated light sensor
+ */
+ public void setLightSensorEnabled(boolean enabled) {
if (enabled && !mRegistered) {
// Wait until we get an event from the sensor indicating ready.
mRegistered = mSensorManager.registerListener(this, mLightSensor,
@@ -92,11 +93,17 @@
}
}
- void stop() {
+ /**
+ * Stops the associated sensor, and cleans up the state
+ */
+ public void stop() {
setLightSensorEnabled(false);
}
- float getAutomaticScreenBrightness() {
+ /**
+ * Gets the automatic screen brightness based on the ambient lux
+ */
+ public float getAutomaticScreenBrightness() {
if (mLastSensorValue < 0 || mLastSensorValue >= mSensorValueToLux.length
|| (!mRegistered
&& mClock.uptimeMillis() - mSensorDisableTime > SENSOR_VALUE_VALID_TIME_MILLIS)) {
@@ -121,8 +128,7 @@
}
/** Functional interface for providing time. */
- @VisibleForTesting
- interface Clock {
+ public interface Clock {
/**
* Returns current time in milliseconds since boot, not counting time spent in deep sleep.
*/
diff --git a/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java b/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java
index 6a88a76..aa17df6 100644
--- a/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java
+++ b/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java
@@ -18,7 +18,9 @@
import android.annotation.Nullable;
import android.content.Context;
+import android.hardware.SensorManager;
import android.hardware.display.DisplayManagerInternal;
+import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.PowerManager;
import android.util.IndentingPrintWriter;
@@ -31,6 +33,8 @@
import com.android.server.display.BrightnessMappingStrategy;
import com.android.server.display.BrightnessSetting;
import com.android.server.display.DisplayBrightnessState;
+import com.android.server.display.DisplayDeviceConfig;
+import com.android.server.display.brightness.strategy.AutoBrightnessFallbackStrategy;
import com.android.server.display.brightness.strategy.AutomaticBrightnessStrategy2;
import com.android.server.display.brightness.strategy.DisplayBrightnessStrategy;
import com.android.server.display.feature.DisplayManagerFlags;
@@ -103,7 +107,8 @@
// The controller for the automatic brightness level.
// TODO(b/265415257): Move to the automatic brightness strategy
@Nullable
- private AutomaticBrightnessController mAutomaticBrightnessController;
+ @VisibleForTesting
+ AutomaticBrightnessController mAutomaticBrightnessController;
/**
* The constructor of DisplayBrightnessController.
@@ -332,14 +337,16 @@
}
/**
- * Set the {@link AutomaticBrightnessController} which is needed to perform nit-to-float-scale
- * conversion.
- * @param automaticBrightnessController The ABC
+ * Sets up the auto brightness and the relevant state for the associated display
*/
- public void setAutomaticBrightnessController(
- AutomaticBrightnessController automaticBrightnessController) {
- mAutomaticBrightnessController = automaticBrightnessController;
- loadNitBasedBrightnessSetting();
+ public void setUpAutoBrightness(AutomaticBrightnessController automaticBrightnessController,
+ SensorManager sensorManager,
+ DisplayDeviceConfig displayDeviceConfig, Handler handler,
+ BrightnessMappingStrategy brightnessMappingStrategy, boolean isEnabled,
+ int leadDisplayId) {
+ setAutomaticBrightnessController(automaticBrightnessController);
+ setUpAutoBrightnessFallbackStrategy(sensorManager, displayDeviceConfig, handler,
+ brightnessMappingStrategy, isEnabled, leadDisplayId);
}
/**
@@ -404,6 +411,17 @@
if (mBrightnessSetting != null) {
mBrightnessSetting.unregisterListener(mBrightnessSettingListener);
}
+ AutoBrightnessFallbackStrategy autoBrightnessFallbackStrategy =
+ getAutoBrightnessFallbackStrategy();
+ if (autoBrightnessFallbackStrategy != null) {
+ autoBrightnessFallbackStrategy.stop();
+ }
+ }
+
+ private AutoBrightnessFallbackStrategy getAutoBrightnessFallbackStrategy() {
+ synchronized (mLock) {
+ return mDisplayBrightnessStrategySelector.getAutoBrightnessFallbackStrategy();
+ }
}
/**
@@ -484,6 +502,33 @@
}
/**
+ * Set the {@link AutomaticBrightnessController} which is needed to perform nit-to-float-scale
+ * conversion.
+ * @param automaticBrightnessController The ABC
+ */
+ @VisibleForTesting
+ void setAutomaticBrightnessController(
+ AutomaticBrightnessController automaticBrightnessController) {
+ mAutomaticBrightnessController = automaticBrightnessController;
+ getAutomaticBrightnessStrategy()
+ .setAutomaticBrightnessController(automaticBrightnessController);
+ loadNitBasedBrightnessSetting();
+ }
+
+ private void setUpAutoBrightnessFallbackStrategy(SensorManager sensorManager,
+ DisplayDeviceConfig displayDeviceConfig, Handler handler,
+ BrightnessMappingStrategy brightnessMappingStrategy, boolean isEnabled,
+ int leadDisplayId) {
+ AutoBrightnessFallbackStrategy autoBrightnessFallbackStrategy =
+ getAutoBrightnessFallbackStrategy();
+ if (autoBrightnessFallbackStrategy != null) {
+ autoBrightnessFallbackStrategy.setupAutoBrightnessFallbackSensor(
+ sensorManager, displayDeviceConfig, handler, brightnessMappingStrategy,
+ isEnabled, leadDisplayId);
+ }
+ }
+
+ /**
* TODO(b/253226419): Remove once auto-brightness is a fully-functioning strategy.
*/
private DisplayBrightnessState addAutomaticBrightnessState(DisplayBrightnessState state) {
diff --git a/services/core/java/com/android/server/display/brightness/DisplayBrightnessStrategySelector.java b/services/core/java/com/android/server/display/brightness/DisplayBrightnessStrategySelector.java
index 282083f..22a21a6 100644
--- a/services/core/java/com/android/server/display/brightness/DisplayBrightnessStrategySelector.java
+++ b/services/core/java/com/android/server/display/brightness/DisplayBrightnessStrategySelector.java
@@ -26,6 +26,7 @@
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.display.brightness.strategy.AutoBrightnessFallbackStrategy;
import com.android.server.display.brightness.strategy.AutomaticBrightnessStrategy;
import com.android.server.display.brightness.strategy.AutomaticBrightnessStrategy2;
import com.android.server.display.brightness.strategy.BoostBrightnessStrategy;
@@ -81,10 +82,14 @@
@Nullable
private final OffloadBrightnessStrategy mOffloadBrightnessStrategy;
+ @Nullable
+ private final AutoBrightnessFallbackStrategy mAutoBrightnessFallbackStrategy;
+
// A collective representation of all the strategies that the selector is aware of. This is
// non null, but the strategies this is tracking can be null
@NonNull
- private final DisplayBrightnessStrategy[] mDisplayBrightnessStrategies;
+ @VisibleForTesting
+ final DisplayBrightnessStrategy[] mDisplayBrightnessStrategies;
@NonNull
private final DisplayManagerFlags mDisplayManagerFlags;
@@ -120,6 +125,9 @@
mAutomaticBrightnessStrategy =
(mDisplayManagerFlags.isRefactorDisplayPowerControllerEnabled())
? mAutomaticBrightnessStrategy1 : mAutomaticBrightnessStrategy2;
+ mAutoBrightnessFallbackStrategy = (mDisplayManagerFlags
+ .isRefactorDisplayPowerControllerEnabled())
+ ? injector.getAutoBrightnessFallbackStrategy() : null;
if (flags.isDisplayOffloadEnabled()) {
mOffloadBrightnessStrategy = injector
.getOffloadBrightnessStrategy(mDisplayManagerFlags);
@@ -129,7 +137,8 @@
mDisplayBrightnessStrategies = new DisplayBrightnessStrategy[]{mInvalidBrightnessStrategy,
mScreenOffBrightnessStrategy, mDozeBrightnessStrategy, mFollowerBrightnessStrategy,
mBoostBrightnessStrategy, mOverrideBrightnessStrategy, mTemporaryBrightnessStrategy,
- mAutomaticBrightnessStrategy1, mOffloadBrightnessStrategy};
+ mAutomaticBrightnessStrategy1, mOffloadBrightnessStrategy,
+ mAutoBrightnessFallbackStrategy};
mAllowAutoBrightnessWhileDozingConfig = context.getResources().getBoolean(
R.bool.config_allowAutoBrightnessWhileDozing);
mOldBrightnessStrategyName = mInvalidBrightnessStrategy.getName();
@@ -168,6 +177,8 @@
&& mOffloadBrightnessStrategy != null && BrightnessUtils.isValidBrightnessValue(
mOffloadBrightnessStrategy.getOffloadScreenBrightness())) {
displayBrightnessStrategy = mOffloadBrightnessStrategy;
+ } else if (isAutoBrightnessFallbackStrategyValid()) {
+ displayBrightnessStrategy = mAutoBrightnessFallbackStrategy;
}
if (mDisplayManagerFlags.isRefactorDisplayPowerControllerEnabled()) {
@@ -210,6 +221,11 @@
return mAllowAutoBrightnessWhileDozingConfig;
}
+ @Nullable
+ public AutoBrightnessFallbackStrategy getAutoBrightnessFallbackStrategy() {
+ return mAutoBrightnessFallbackStrategy;
+ }
+
/**
* Dumps the state of this class.
*/
@@ -229,6 +245,13 @@
}
}
+ private boolean isAutoBrightnessFallbackStrategyValid() {
+ return mDisplayManagerFlags.isRefactorDisplayPowerControllerEnabled()
+ && mAutoBrightnessFallbackStrategy != null
+ && getAutomaticBrightnessStrategy().shouldUseAutoBrightness()
+ && mAutoBrightnessFallbackStrategy.isValid();
+ }
+
private boolean isAutomaticBrightnessStrategyValid(
StrategySelectionRequest strategySelectionRequest) {
mAutomaticBrightnessStrategy1.setAutoBrightnessState(
@@ -245,12 +268,13 @@
DisplayBrightnessStrategy selectedDisplayBrightnessStrategy,
StrategySelectionRequest strategySelectionRequest) {
return new StrategySelectionNotifyRequest(
- strategySelectionRequest.getDisplayPowerRequest(),
+ strategySelectionRequest.getDisplayPowerRequest(),
strategySelectionRequest.getTargetDisplayState(),
selectedDisplayBrightnessStrategy,
strategySelectionRequest.getLastUserSetScreenBrightness(),
strategySelectionRequest.isUserSetBrightnessChanged(),
- isAllowAutoBrightnessWhileDozingConfig());
+ isAllowAutoBrightnessWhileDozingConfig(),
+ getAutomaticBrightnessStrategy().shouldUseAutoBrightness());
}
private void postProcess(StrategySelectionNotifyRequest strategySelectionNotifyRequest) {
@@ -319,5 +343,9 @@
DisplayManagerFlags displayManagerFlags) {
return new OffloadBrightnessStrategy(displayManagerFlags);
}
+
+ AutoBrightnessFallbackStrategy getAutoBrightnessFallbackStrategy() {
+ return new AutoBrightnessFallbackStrategy(/* injector= */ null);
+ }
}
}
diff --git a/services/core/java/com/android/server/display/brightness/StrategySelectionNotifyRequest.java b/services/core/java/com/android/server/display/brightness/StrategySelectionNotifyRequest.java
index 6e6c972..bfa90e2 100644
--- a/services/core/java/com/android/server/display/brightness/StrategySelectionNotifyRequest.java
+++ b/services/core/java/com/android/server/display/brightness/StrategySelectionNotifyRequest.java
@@ -45,18 +45,22 @@
// True if light sensor is to be used to automatically determine doze screen brightness.
private final boolean mAllowAutoBrightnessWhileDozingConfig;
+ // True if the auto brightness is enabled in the settings
+ private final boolean mIsAutoBrightnessEnabled;
public StrategySelectionNotifyRequest(
DisplayManagerInternal.DisplayPowerRequest displayPowerRequest, int targetDisplayState,
DisplayBrightnessStrategy displayBrightnessStrategy,
float lastUserSetScreenBrightness,
- boolean userSetBrightnessChanged, boolean allowAutoBrightnessWhileDozingConfig) {
+ boolean userSetBrightnessChanged, boolean allowAutoBrightnessWhileDozingConfig,
+ boolean isAutoBrightnessEnabled) {
mDisplayPowerRequest = displayPowerRequest;
mTargetDisplayState = targetDisplayState;
mSelectedDisplayBrightnessStrategy = displayBrightnessStrategy;
mLastUserSetScreenBrightness = lastUserSetScreenBrightness;
mUserSetBrightnessChanged = userSetBrightnessChanged;
mAllowAutoBrightnessWhileDozingConfig = allowAutoBrightnessWhileDozingConfig;
+ mIsAutoBrightnessEnabled = isAutoBrightnessEnabled;
}
public DisplayBrightnessStrategy getSelectedDisplayBrightnessStrategy() {
@@ -76,14 +80,15 @@
&& mUserSetBrightnessChanged == other.isUserSetBrightnessChanged()
&& mLastUserSetScreenBrightness == other.getLastUserSetScreenBrightness()
&& mAllowAutoBrightnessWhileDozingConfig
- == other.isAllowAutoBrightnessWhileDozingConfig();
+ == other.isAllowAutoBrightnessWhileDozingConfig()
+ && mIsAutoBrightnessEnabled == other.isAutoBrightnessEnabled();
}
@Override
public int hashCode() {
return Objects.hash(mSelectedDisplayBrightnessStrategy, mDisplayPowerRequest,
mTargetDisplayState, mUserSetBrightnessChanged, mLastUserSetScreenBrightness,
- mAllowAutoBrightnessWhileDozingConfig);
+ mAllowAutoBrightnessWhileDozingConfig, mIsAutoBrightnessEnabled);
}
public float getLastUserSetScreenBrightness() {
@@ -106,6 +111,10 @@
return mAllowAutoBrightnessWhileDozingConfig;
}
+ public boolean isAutoBrightnessEnabled() {
+ return mIsAutoBrightnessEnabled;
+ }
+
/**
* A utility to stringify a StrategySelectionNotifyRequest
*/
@@ -116,6 +125,7 @@
+ " mSelectedDisplayBrightnessStrategy=" + mSelectedDisplayBrightnessStrategy
+ " mLastUserSetScreenBrightness=" + mLastUserSetScreenBrightness
+ " mUserSetBrightnessChanged=" + mUserSetBrightnessChanged
- + " mAllowAutoBrightnessWhileDozingConfig=" + mAllowAutoBrightnessWhileDozingConfig;
+ + " mAllowAutoBrightnessWhileDozingConfig=" + mAllowAutoBrightnessWhileDozingConfig
+ + " mIsAutoBrightnessEnabled=" + mIsAutoBrightnessEnabled;
}
}
diff --git a/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java b/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java
index a46975fb..11ef577 100644
--- a/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java
+++ b/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java
@@ -285,7 +285,8 @@
List<BrightnessStateModifier> modifiers = new ArrayList<>();
modifiers.add(new DisplayDimModifier(context));
modifiers.add(new BrightnessLowPowerModeModifier());
- if (flags.isEvenDimmerEnabled() && displayDeviceConfig != null) {
+ if (flags.isEvenDimmerEnabled() && displayDeviceConfig != null
+ && displayDeviceConfig.isEvenDimmerAvailable()) {
modifiers.add(new BrightnessLowLuxModifier(handler, listener, context,
displayDeviceConfig));
}
diff --git a/services/core/java/com/android/server/display/brightness/clamper/BrightnessLowLuxModifier.java b/services/core/java/com/android/server/display/brightness/clamper/BrightnessLowLuxModifier.java
index a3dfe22..7ba4a4d 100644
--- a/services/core/java/com/android/server/display/brightness/clamper/BrightnessLowLuxModifier.java
+++ b/services/core/java/com/android/server/display/brightness/clamper/BrightnessLowLuxModifier.java
@@ -87,9 +87,7 @@
mContentResolver, Settings.Secure.EVEN_DIMMER_MIN_NITS,
/* def= */ MIN_NITS_DEFAULT, userId);
- boolean isActive = Settings.Secure.getFloatForUser(mContentResolver,
- Settings.Secure.EVEN_DIMMER_ACTIVATED,
- /* def= */ 0, userId) == 1.0f && mAutoBrightnessEnabled;
+ boolean isActive = isSettingEnabled() && mAutoBrightnessEnabled;
float luxBasedNitsLowerBound = mDisplayDeviceConfig.getMinNitsFromLux(mAmbientLux);
@@ -202,6 +200,17 @@
pw.println(" mMinNitsAllowed=" + mMinNitsAllowed);
}
+ /**
+ * Defaults to true, on devices where setting is unset.
+ *
+ * @return if setting indicates feature is enabled
+ */
+ private boolean isSettingEnabled() {
+ return Settings.Secure.getFloatForUser(mContentResolver,
+ Settings.Secure.EVEN_DIMMER_ACTIVATED,
+ /* def= */ 1.0f, UserHandle.USER_CURRENT) == 1.0f;
+ }
+
private float getBrightnessFromNits(float nits) {
return mDisplayDeviceConfig.getBrightnessFromBacklight(
mDisplayDeviceConfig.getBacklightFromNits(nits));
diff --git a/services/core/java/com/android/server/display/brightness/strategy/AutoBrightnessFallbackStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/AutoBrightnessFallbackStrategy.java
new file mode 100644
index 0000000..16bf177f
--- /dev/null
+++ b/services/core/java/com/android/server/display/brightness/strategy/AutoBrightnessFallbackStrategy.java
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.display.brightness.strategy;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.hardware.Sensor;
+import android.hardware.SensorManager;
+import android.os.Handler;
+import android.os.SystemClock;
+import android.util.IndentingPrintWriter;
+import android.view.Display;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.display.BrightnessMappingStrategy;
+import com.android.server.display.DisplayBrightnessState;
+import com.android.server.display.DisplayDeviceConfig;
+import com.android.server.display.ScreenOffBrightnessSensorController;
+import com.android.server.display.brightness.BrightnessReason;
+import com.android.server.display.brightness.BrightnessUtils;
+import com.android.server.display.brightness.StrategyExecutionRequest;
+import com.android.server.display.brightness.StrategySelectionNotifyRequest;
+import com.android.server.display.layout.Layout;
+import com.android.server.display.utils.SensorUtils;
+
+import java.io.PrintWriter;
+
+/**
+ * This strategy is used when the screen has just turned ON, with auto-brightness ON but there is
+ * no valid lux values available yet. In such a case, if configured, we set the brightness state
+ * from this
+ */
+public final class AutoBrightnessFallbackStrategy implements DisplayBrightnessStrategy {
+
+ @Nullable
+ private ScreenOffBrightnessSensorController mScreenOffBrightnessSensorController;
+ @VisibleForTesting
+ @Nullable
+ Sensor mScreenOffBrightnessSensor;
+
+ // Indicates if the associated LogicalDisplay is enabled or not.
+ private boolean mIsEnabled;
+
+ // Represents if the associated display is a lead display or not. If not, the variable
+ // represents the lead display ID
+ private int mLeadDisplayId;
+
+ @NonNull
+ private final Injector mInjector;
+
+ public AutoBrightnessFallbackStrategy(Injector injector) {
+ mInjector = (injector == null) ? new RealInjector() : injector;
+ }
+
+ @Override
+ public DisplayBrightnessState updateBrightness(
+ StrategyExecutionRequest strategyExecutionRequest) {
+ assert mScreenOffBrightnessSensorController != null;
+ float brightness = mScreenOffBrightnessSensorController.getAutomaticScreenBrightness();
+ BrightnessReason brightnessReason = new BrightnessReason();
+ brightnessReason.setReason(BrightnessReason.REASON_SCREEN_OFF_BRIGHTNESS_SENSOR);
+ return new DisplayBrightnessState.Builder()
+ .setBrightness(brightness)
+ .setSdrBrightness(brightness)
+ .setBrightnessReason(brightnessReason)
+ .setDisplayBrightnessStrategyName(getName())
+ .setShouldUpdateScreenBrightnessSetting(brightness
+ != strategyExecutionRequest.getCurrentScreenBrightness())
+ .build();
+ }
+
+ @NonNull
+ @Override
+ public String getName() {
+ return "AutoBrightnessFallbackStrategy";
+ }
+
+ @Override
+ public int getReason() {
+ return BrightnessReason.REASON_SCREEN_OFF_BRIGHTNESS_SENSOR;
+ }
+
+ @Override
+ public void dump(PrintWriter writer) {
+ writer.println("AutoBrightnessFallbackStrategy:");
+ writer.println(" mLeadDisplayId=" + mLeadDisplayId);
+ writer.println(" mIsEnabled=" + mIsEnabled);
+ if (mScreenOffBrightnessSensorController != null) {
+ IndentingPrintWriter ipw = new IndentingPrintWriter(writer, " ");
+ mScreenOffBrightnessSensorController.dump(ipw);
+ }
+ }
+
+ @Override
+ public void strategySelectionPostProcessor(
+ StrategySelectionNotifyRequest strategySelectionNotifyRequest) {
+ if (mScreenOffBrightnessSensorController != null) {
+ int targetDisplayState = strategySelectionNotifyRequest.getTargetDisplayState();
+ mScreenOffBrightnessSensorController.setLightSensorEnabled(
+ strategySelectionNotifyRequest.isAutoBrightnessEnabled() && mIsEnabled
+ && (targetDisplayState == Display.STATE_OFF
+ || (targetDisplayState == Display.STATE_DOZE
+ && !strategySelectionNotifyRequest
+ .isAllowAutoBrightnessWhileDozingConfig()))
+ && mLeadDisplayId == Layout.NO_LEAD_DISPLAY);
+ }
+ }
+
+ /**
+ * Gets the associated ScreenOffBrightnessSensorController, controlling the brightness when
+ * auto-brightness is enabled, but the lux is not valid yet.
+ */
+ public ScreenOffBrightnessSensorController getScreenOffBrightnessSensorController() {
+ return mScreenOffBrightnessSensorController;
+ }
+
+ /**
+ * Sets up the auto brightness fallback sensor
+ */
+ public void setupAutoBrightnessFallbackSensor(SensorManager sensorManager,
+ DisplayDeviceConfig displayDeviceConfig, Handler handler,
+ BrightnessMappingStrategy brightnessMappingStrategy, boolean isEnabled,
+ int leadDisplayId) {
+ mIsEnabled = isEnabled;
+ mLeadDisplayId = leadDisplayId;
+ if (mScreenOffBrightnessSensorController != null) {
+ mScreenOffBrightnessSensorController.stop();
+ mScreenOffBrightnessSensorController = null;
+ }
+ loadScreenOffBrightnessSensor(sensorManager, displayDeviceConfig);
+ int[] sensorValueToLux = displayDeviceConfig.getScreenOffBrightnessSensorValueToLux();
+ if (mScreenOffBrightnessSensor != null && sensorValueToLux != null) {
+ mScreenOffBrightnessSensorController =
+ mInjector.getScreenOffBrightnessSensorController(
+ sensorManager,
+ mScreenOffBrightnessSensor,
+ handler,
+ SystemClock::uptimeMillis,
+ sensorValueToLux,
+ brightnessMappingStrategy);
+ }
+ }
+
+ /**
+ * Stops the associated ScreenOffBrightnessSensorController responsible for managing the
+ * brightness when this strategy is selected
+ */
+ public void stop() {
+ if (mScreenOffBrightnessSensorController != null) {
+ mScreenOffBrightnessSensorController.stop();
+ }
+ }
+
+ /**
+ * Checks if the strategy is valid, based on its internal state. Note that there can still be
+ * external factors like auto-brightness not being enabled because of which this strategy is not
+ * selected
+ */
+ public boolean isValid() {
+ return mScreenOffBrightnessSensorController != null
+ && BrightnessUtils.isValidBrightnessValue(
+ mScreenOffBrightnessSensorController.getAutomaticScreenBrightness());
+ }
+
+ private void loadScreenOffBrightnessSensor(SensorManager sensorManager,
+ DisplayDeviceConfig displayDeviceConfig) {
+ mScreenOffBrightnessSensor = mInjector.getScreenOffBrightnessSensor(sensorManager,
+ displayDeviceConfig);
+ }
+
+
+ @VisibleForTesting
+ interface Injector {
+ Sensor getScreenOffBrightnessSensor(SensorManager sensorManager,
+ DisplayDeviceConfig displayDeviceConfig);
+
+ ScreenOffBrightnessSensorController getScreenOffBrightnessSensorController(
+ SensorManager sensorManager,
+ Sensor lightSensor,
+ Handler handler,
+ ScreenOffBrightnessSensorController.Clock clock,
+ int[] sensorValueToLux,
+ BrightnessMappingStrategy brightnessMapper);
+ }
+
+ static class RealInjector implements Injector {
+ @Override
+ public Sensor getScreenOffBrightnessSensor(SensorManager sensorManager,
+ DisplayDeviceConfig displayDeviceConfig) {
+ return SensorUtils.findSensor(sensorManager,
+ displayDeviceConfig.getScreenOffBrightnessSensor(), SensorUtils.NO_FALLBACK);
+ }
+
+ @Override
+ public ScreenOffBrightnessSensorController getScreenOffBrightnessSensorController(
+ SensorManager sensorManager, Sensor lightSensor, Handler handler,
+ ScreenOffBrightnessSensorController.Clock clock, int[] sensorValueToLux,
+ BrightnessMappingStrategy brightnessMapper) {
+ return new ScreenOffBrightnessSensorController(
+ sensorManager, lightSensor, handler, clock, sensorValueToLux, brightnessMapper);
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy.java
index 5c4fa842..2305228 100644
--- a/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy.java
+++ b/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy.java
@@ -360,11 +360,11 @@
* @param brightnessEvent Event object to populate with details about why the specific
* brightness was chosen.
*/
- public float getAutomaticScreenBrightnessBasedOnLastObservedLux(
+ public float getAutomaticScreenBrightnessBasedOnLastUsedLux(
BrightnessEvent brightnessEvent) {
float brightness = (mAutomaticBrightnessController != null)
? mAutomaticBrightnessController
- .getAutomaticScreenBrightnessBasedOnLastObservedLux(brightnessEvent)
+ .getAutomaticScreenBrightnessBasedOnLastUsedLux(brightnessEvent)
: PowerManager.BRIGHTNESS_INVALID_FLOAT;
adjustAutomaticBrightnessStateIfValid(brightness);
return brightness;
diff --git a/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy2.java b/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy2.java
index 25e8b23..58670c9 100644
--- a/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy2.java
+++ b/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy2.java
@@ -279,11 +279,11 @@
* @param brightnessEvent Event object to populate with details about why the specific
* brightness was chosen.
*/
- public float getAutomaticScreenBrightnessBasedOnLastObservedLux(
+ public float getAutomaticScreenBrightnessBasedOnLastUsedLux(
BrightnessEvent brightnessEvent) {
float brightness = (mAutomaticBrightnessController != null)
? mAutomaticBrightnessController
- .getAutomaticScreenBrightnessBasedOnLastObservedLux(brightnessEvent)
+ .getAutomaticScreenBrightnessBasedOnLastUsedLux(brightnessEvent)
: PowerManager.BRIGHTNESS_INVALID_FLOAT;
adjustAutomaticBrightnessStateIfValid(brightness);
return brightness;
diff --git a/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionBackupHelper.java b/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionBackupHelper.java
index d494be5..e91de37 100644
--- a/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionBackupHelper.java
+++ b/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionBackupHelper.java
@@ -123,8 +123,7 @@
* Returns the system-gender to be backed up as a data-blob.
*/
public byte[] getSystemBackupPayload(int userId) {
- int gender = mGrammaticalGenderService.getSystemGrammaticalGender(mAttributionSource,
- userId);
+ int gender = mGrammaticalGenderService.getSystemGrammaticalGender(userId);
return intToByteArray(gender);
}
@@ -167,7 +166,7 @@
BackupManager.dataChanged(SYSTEM_BACKUP_PACKAGE_KEY);
}
- private byte[] convertToByteArray(HashMap<String, Integer> pkgGenderInfo) {
+ private static byte[] convertToByteArray(HashMap<String, Integer> pkgGenderInfo) {
try (final ByteArrayOutputStream out = new ByteArrayOutputStream();
final ObjectOutputStream objStream = new ObjectOutputStream(out)) {
objStream.writeObject(pkgGenderInfo);
@@ -178,22 +177,22 @@
}
}
- private byte[] intToByteArray(final int gender) {
+ private static byte[] intToByteArray(final int gender) {
ByteBuffer bb = ByteBuffer.allocate(4);
bb.putInt(gender);
return bb.array();
}
- private int convertByteArrayToInt(byte[] intBytes) {
+ private static int convertByteArrayToInt(byte[] intBytes) {
ByteBuffer byteBuffer = ByteBuffer.wrap(intBytes);
return byteBuffer.getInt();
}
- private HashMap<String, Integer> readFromByteArray(byte[] payload) {
+ private static HashMap<String, Integer> readFromByteArray(byte[] payload) {
HashMap<String, Integer> data = new HashMap<>();
- try (ByteArrayInputStream byteIn = new ByteArrayInputStream(payload);
- ObjectInputStream in = new ObjectInputStream(byteIn)) {
+ try (var byteIn = new ByteArrayInputStream(payload);
+ var in = new ObjectInputStream(byteIn)) {
data = (HashMap<String, Integer>) in.readObject();
} catch (IOException | ClassNotFoundException e) {
Log.e(TAG, "cannot convert payload to HashMap.", e);
@@ -205,10 +204,10 @@
private void cleanStagedDataForOldEntries() {
for (int i = 0; i < mCache.size(); i++) {
int userId = mCache.keyAt(i);
- StagedData stagedData = mCache.get(userId);
+ StagedData stagedData = mCache.valueAt(userId);
if (stagedData.mCreationTimeMillis
< mClock.millis() - STAGE_DATA_RETENTION_PERIOD.toMillis()) {
- mCache.remove(userId);
+ mCache.removeAt(i--);
}
}
}
diff --git a/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionManagerInternal.java b/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionManagerInternal.java
index 2816d08..7eb971c 100644
--- a/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionManagerInternal.java
+++ b/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionManagerInternal.java
@@ -16,7 +16,6 @@
package com.android.server.grammaticalinflection;
-import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.res.Configuration;
@@ -41,7 +40,7 @@
public abstract void stageAndApplyRestoredPayload(byte[] payload, int userId);
/**
- * Get the current system grammatical gender of privileged application.
+ * Get the current system grammatical gender for the particular user.
*
* @return the value of grammatical gender
*
@@ -50,18 +49,25 @@
public abstract @Configuration.GrammaticalGender int getSystemGrammaticalGender(int userId);
/**
- * Retrieve the system grammatical gender.
+ * Get the final merged value of the global grammatical gender, user- or devsettings-set.
*
* @return the value of grammatical gender
*
*/
- public abstract @Configuration.GrammaticalGender int retrieveSystemGrammaticalGender(
- @NonNull Configuration configuration);
+ public abstract @Configuration.GrammaticalGender int mergedFinalSystemGrammaticalGender();
+
+ /**
+ * Get the grammatical gender from developer settings global override.
+ *
+ * @return the value of grammatical gender
+ */
+ public abstract
+ @Configuration.GrammaticalGender int getGrammaticalGenderFromDeveloperSettings();
/**
* Whether the package can get the system grammatical gender or not.
*/
- public abstract boolean canGetSystemGrammaticalGender(int uid, @Nullable String packageName);
+ public abstract boolean canGetSystemGrammaticalGender(int uid);
/**
@@ -74,4 +80,3 @@
*/
public abstract void applyRestoredSystemPayload(byte[] payload, int userId);
}
-
diff --git a/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionService.java b/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionService.java
index 93a71b9..e242164 100644
--- a/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionService.java
+++ b/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionService.java
@@ -17,7 +17,6 @@
package com.android.server.grammaticalinflection;
import static android.app.Flags.systemTermsOfAddressEnabled;
-import static android.content.res.Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED;
import static com.android.server.grammaticalinflection.GrammaticalInflectionUtils.checkSystemGrammaticalGenderPermission;
@@ -43,6 +42,7 @@
import android.util.SparseIntArray;
import android.util.Xml;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.XmlUtils;
import com.android.modules.utils.TypedXmlPullParser;
@@ -126,7 +126,7 @@
@Override
public void setSystemWideGrammaticalGender(int grammaticalGender, int userId) {
- isCallerAllowed();
+ enforceCallerPermissions();
GrammaticalInflectionService.this.setSystemWideGrammaticalGender(grammaticalGender,
userId);
}
@@ -138,18 +138,16 @@
+ " does not have READ_SYSTEM_GRAMMATICAL_GENDER permission.");
}
return checkSystemTermsOfAddressIsEnabled()
- ? GrammaticalInflectionService.this.getSystemGrammaticalGender(
- attributionSource, userId)
- : GRAMMATICAL_GENDER_NOT_SPECIFIED;
+ ? GrammaticalInflectionService.this.getSystemGrammaticalGender(userId)
+ : Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED;
}
@Override
public int peekSystemGrammaticalGenderByUserId(AttributionSource attributionSource,
int userId) {
return canGetSystemGrammaticalGender(attributionSource)
- ? GrammaticalInflectionService.this.getSystemGrammaticalGender(
- attributionSource, userId)
- : GRAMMATICAL_GENDER_NOT_SPECIFIED;
+ ? GrammaticalInflectionService.this.getSystemGrammaticalGender(userId)
+ : Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED;
}
@Override
@@ -163,11 +161,10 @@
private final class GrammaticalInflectionManagerInternalImpl
extends GrammaticalInflectionManagerInternal {
-
@Override
@Nullable
public byte[] getBackupPayload(int userId) {
- isCallerAllowed();
+ enforceCallerPermissions();
return mBackupHelper.getBackupPayload(userId);
}
@@ -179,7 +176,7 @@
@Override
@Nullable
public byte[] getSystemBackupPayload(int userId) {
- isCallerAllowed();
+ enforceCallerPermissions();
return mBackupHelper.getSystemBackupPayload(userId);
}
@@ -191,30 +188,35 @@
@Override
public int getSystemGrammaticalGender(int userId) {
return checkSystemTermsOfAddressIsEnabled()
- ? GrammaticalInflectionService.this.getSystemGrammaticalGender(
- mContext.getAttributionSource(), userId)
- : GRAMMATICAL_GENDER_NOT_SPECIFIED;
+ ? GrammaticalInflectionService.this.getSystemGrammaticalGender(userId)
+ : Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED;
}
@Override
- public int retrieveSystemGrammaticalGender(Configuration configuration) {
+ public int mergedFinalSystemGrammaticalGender() {
int systemGrammaticalGender = getSystemGrammaticalGender(mContext.getUserId());
// Retrieve the grammatical gender from system property, set it into
// configuration which will get updated later if the grammatical gender raw value of
// current configuration is {@link Configuration#GRAMMATICAL_GENDER_UNDEFINED}.
- if (configuration.getGrammaticalGenderRaw()
- == Configuration.GRAMMATICAL_GENDER_UNDEFINED
- || systemGrammaticalGender <= Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED) {
- systemGrammaticalGender = SystemProperties.getInt(GRAMMATICAL_GENDER_PROPERTY,
- Configuration.GRAMMATICAL_GENDER_UNDEFINED);
+ if (systemGrammaticalGender == Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED) {
+ systemGrammaticalGender = getGrammaticalGenderFromDeveloperSettings();
}
- return systemGrammaticalGender;
+ return systemGrammaticalGender == Configuration.GRAMMATICAL_GENDER_UNDEFINED
+ ? Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED : systemGrammaticalGender;
}
@Override
- public boolean canGetSystemGrammaticalGender(int uid, String packageName) {
- AttributionSource attributionSource = new AttributionSource.Builder(
- uid).setPackageName(packageName).build();
+ public int getGrammaticalGenderFromDeveloperSettings() {
+ return SystemProperties.getInt(GRAMMATICAL_GENDER_PROPERTY,
+ Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED);
+ }
+
+ @Override
+ public boolean canGetSystemGrammaticalGender(int uid) {
+ if (uid == Process.SYSTEM_UID) {
+ return true;
+ }
+ var attributionSource = new AttributionSource.Builder(uid).build();
return GrammaticalInflectionService.this.canGetSystemGrammaticalGender(
attributionSource);
}
@@ -225,7 +227,7 @@
mActivityTaskManagerInternal.getApplicationConfig(appPackageName, userId);
if (appConfig == null || appConfig.mGrammaticalGender == null) {
- return GRAMMATICAL_GENDER_NOT_SPECIFIED;
+ return Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED;
} else {
return appConfig.mGrammaticalGender;
}
@@ -239,9 +241,10 @@
userId);
if (!SystemProperties.getBoolean(GRAMMATICAL_INFLECTION_ENABLED, true)) {
- if (preValue != GRAMMATICAL_GENDER_NOT_SPECIFIED) {
+ if (preValue != Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED) {
Log.d(TAG, "Clearing the user's grammatical gender setting");
- updater.setGrammaticalGender(GRAMMATICAL_GENDER_NOT_SPECIFIED).commit();
+ updater.setGrammaticalGender(
+ Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED).commit();
}
return;
}
@@ -250,49 +253,48 @@
FrameworkStatsLog.write(FrameworkStatsLog.APPLICATION_GRAMMATICAL_INFLECTION_CHANGED,
FrameworkStatsLog.APPLICATION_GRAMMATICAL_INFLECTION_CHANGED__SOURCE_ID__OTHERS,
uid,
- gender != GRAMMATICAL_GENDER_NOT_SPECIFIED,
- preValue != GRAMMATICAL_GENDER_NOT_SPECIFIED);
+ gender != Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED,
+ preValue != Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED);
updater.setGrammaticalGender(gender).commit();
}
protected void setSystemWideGrammaticalGender(int grammaticalGender, int userId) {
- Trace.beginSection("GrammaticalInflectionService.setSystemWideGrammaticalGender");
- if (!GrammaticalInflectionManager.VALID_GRAMMATICAL_GENDER_VALUES.contains(
- grammaticalGender)) {
- throw new IllegalArgumentException("Unknown grammatical gender");
- }
-
- if (!checkSystemTermsOfAddressIsEnabled()) {
- if (grammaticalGender == GRAMMATICAL_GENDER_NOT_SPECIFIED) {
- return;
+ try {
+ if (!checkSystemTermsOfAddressIsEnabled()) {
+ return; // Nothing to do, and the flag can't get flipped at the runtime.
}
- Log.d(TAG, "Clearing the system grammatical gender setting");
- grammaticalGender = GRAMMATICAL_GENDER_NOT_SPECIFIED;
- }
- synchronized (mLock) {
+ Trace.beginSection("GrammaticalInflectionService.setSystemWideGrammaticalGender");
+ if (!GrammaticalInflectionManager.VALID_GRAMMATICAL_GENDER_VALUES.contains(
+ grammaticalGender)) {
+ throw new IllegalArgumentException("Unknown grammatical gender");
+ }
+
final File file = getGrammaticalGenderFile(userId);
- final AtomicFile atomicFile = new AtomicFile(file);
- FileOutputStream stream = null;
- try {
- stream = atomicFile.startWrite();
- stream.write(toXmlByteArray(grammaticalGender, stream));
- atomicFile.finishWrite(stream);
- mGrammaticalGenderCache.put(userId, grammaticalGender);
- } catch (IOException e) {
- Log.e(TAG, "Failed to write file " + atomicFile, e);
- if (stream != null) {
- atomicFile.failWrite(stream);
+ synchronized (mLock) {
+ final AtomicFile atomicFile = new AtomicFile(file);
+ FileOutputStream stream = null;
+ try {
+ stream = atomicFile.startWrite();
+ stream.write(toXmlByteArray(grammaticalGender, stream));
+ atomicFile.finishWrite(stream);
+ mGrammaticalGenderCache.put(userId, grammaticalGender);
+ } catch (IOException e) {
+ Log.e(TAG, "Failed to write file " + atomicFile, e);
+ if (stream != null) {
+ atomicFile.failWrite(stream);
+ }
+ throw new RuntimeException(e);
}
- throw new RuntimeException(e);
}
+ updateConfiguration(grammaticalGender, userId);
+ } finally {
+ Trace.endSection();
}
- updateConfiguration(grammaticalGender, userId);
- Trace.endSection();
}
- private void updateConfiguration(int grammaticalGender, int userId) {
+ private static void updateConfiguration(int grammaticalGender, int userId) {
try {
Configuration config = new Configuration();
int preValue = config.getGrammaticalGender();
@@ -301,54 +303,47 @@
FrameworkStatsLog.write(FrameworkStatsLog.SYSTEM_GRAMMATICAL_INFLECTION_CHANGED,
FrameworkStatsLog.SYSTEM_GRAMMATICAL_INFLECTION_CHANGED__SOURCE_ID__SYSTEM,
userId,
- grammaticalGender != GRAMMATICAL_GENDER_NOT_SPECIFIED,
- preValue != GRAMMATICAL_GENDER_NOT_SPECIFIED);
+ grammaticalGender != Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED,
+ preValue != Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED);
GrammaticalInflectionBackupHelper.notifyBackupManager();
} catch (RemoteException e) {
Log.w(TAG, "Can not update configuration", e);
}
}
- public int getSystemGrammaticalGender(AttributionSource attributionSource, int userId) {
- String packageName = attributionSource.getPackageName();
- if (packageName == null) {
- Log.d(TAG, "Package name is null.");
- return GRAMMATICAL_GENDER_NOT_SPECIFIED;
- }
-
+ /**
+ * Returns the system global grammatical gender value for the requested user.
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PROTECTED)
+ public int getSystemGrammaticalGender(int userId) {
synchronized (mLock) {
int grammaticalGender = mGrammaticalGenderCache.get(userId);
- return grammaticalGender < 0 ? GRAMMATICAL_GENDER_NOT_SPECIFIED : grammaticalGender;
+ return grammaticalGender < 0
+ ? Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED : grammaticalGender;
}
}
- private File getGrammaticalGenderFile(int userId) {
+ private static File getGrammaticalGenderFile(int userId) {
final File dir = new File(Environment.getDataSystemCeDirectory(userId),
TAG_GRAMMATICAL_INFLECTION);
return new File(dir, USER_SETTINGS_FILE_NAME);
}
- private byte[] toXmlByteArray(int grammaticalGender, FileOutputStream fileStream) {
-
- try {
- ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
- TypedXmlSerializer out = Xml.resolveSerializer(fileStream);
- out.setOutput(outputStream, StandardCharsets.UTF_8.name());
- out.startDocument(/* encoding= */ null, /* standalone= */ true);
- out.startTag(null, TAG_GRAMMATICAL_INFLECTION);
- out.attributeInt(null, ATTR_NAME, grammaticalGender);
- out.endTag(null, TAG_GRAMMATICAL_INFLECTION);
- out.endDocument();
-
- return outputStream.toByteArray();
- } catch (IOException e) {
- return null;
- }
+ private static byte[] toXmlByteArray(int grammaticalGender, FileOutputStream fileStream)
+ throws IOException {
+ var outputStream = new ByteArrayOutputStream();
+ TypedXmlSerializer out = Xml.resolveSerializer(fileStream);
+ out.setOutput(outputStream, StandardCharsets.UTF_8.name());
+ out.startDocument(/* encoding= */ null, /* standalone= */ true);
+ out.startTag(null, TAG_GRAMMATICAL_INFLECTION);
+ out.attributeInt(null, ATTR_NAME, grammaticalGender);
+ out.endTag(null, TAG_GRAMMATICAL_INFLECTION);
+ out.endDocument();
+ return outputStream.toByteArray();
}
- private int getGrammaticalGenderFromXml(TypedXmlPullParser parser)
+ private static int getGrammaticalGenderFromXml(TypedXmlPullParser parser)
throws IOException, XmlPullParserException {
-
XmlUtils.nextElement(parser);
while (parser.getEventType() != XmlPullParser.END_DOCUMENT) {
String tagName = parser.getName();
@@ -359,20 +354,20 @@
}
}
- return GRAMMATICAL_GENDER_NOT_SPECIFIED;
+ return Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED;
}
- private void isCallerAllowed() {
+ private void enforceCallerPermissions() {
int callingUid = Binder.getCallingUid();
if (callingUid != Process.SYSTEM_UID && callingUid != Process.SHELL_UID
&& callingUid != Process.ROOT_UID) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.CHANGE_CONFIGURATION,
- "Caller must be system, shell, root or has CHANGE_CONFIGURATION permission.");
+ "Caller must be system, shell, root or hold CHANGE_CONFIGURATION permission.");
}
}
- private boolean checkSystemTermsOfAddressIsEnabled() {
+ private static boolean checkSystemTermsOfAddressIsEnabled() {
if (!systemTermsOfAddressEnabled()) {
Log.d(TAG, "The flag must be enabled to allow calling the API.");
return false;
@@ -387,25 +382,31 @@
@Override
public void onUserUnlocked(TargetUser user) {
+ if (!checkSystemTermsOfAddressIsEnabled()) {
+ return;
+ }
IoThread.getHandler().post(() -> {
- int userId = user.getUserIdentifier();
+ final int userId = user.getUserIdentifier();
final File file = getGrammaticalGenderFile(userId);
+ final int grammaticalGender;
synchronized (mLock) {
if (!file.exists()) {
Log.d(TAG, "User " + userId + " doesn't have the grammatical gender file.");
return;
}
- if (mGrammaticalGenderCache.indexOfKey(userId) < 0) {
- try (FileInputStream in = new FileInputStream(file)) {
- final TypedXmlPullParser parser = Xml.resolvePullParser(in);
- int grammaticalGender = getGrammaticalGenderFromXml(parser);
- mGrammaticalGenderCache.put(userId, grammaticalGender);
- updateConfiguration(grammaticalGender, userId);
- } catch (IOException | XmlPullParserException e) {
- Log.e(TAG, "Failed to parse XML configuration from " + file, e);
- }
+ if (mGrammaticalGenderCache.indexOfKey(userId) >= 0) {
+ return;
+ }
+ try (FileInputStream in = new FileInputStream(file)) {
+ final TypedXmlPullParser parser = Xml.resolvePullParser(in);
+ grammaticalGender = getGrammaticalGenderFromXml(parser);
+ mGrammaticalGenderCache.put(userId, grammaticalGender);
+ } catch (IOException | XmlPullParserException e) {
+ Log.e(TAG, "Failed to parse XML configuration from " + file, e);
+ return;
}
}
+ updateConfiguration(grammaticalGender, userId);
});
}
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecController.java b/services/core/java/com/android/server/hdmi/HdmiCecController.java
index f6dfc9e..cd2c037 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecController.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecController.java
@@ -350,7 +350,7 @@
* {@link HdmiCecNetwork} only.
*
* @return CEC physical address of the device. The range of success address
- * is between 0x0000 and 0xFFFF. If failed it returns -1
+ * is between 0x0000 and 0xFFFE. If failed it returns INVALID_PHYSICAL_ADDRESS.
*/
@ServiceThreadOnly
int getPhysicalAddress() {
@@ -1315,7 +1315,7 @@
hdmiPortInfo[i] = new HdmiPortInfo.Builder(
portInfo.portId,
portInfo.type,
- portInfo.physicalAddress)
+ Short.toUnsignedInt(portInfo.physicalAddress))
.setCecSupported(portInfo.cecSupported)
.setMhlSupported(false)
.setArcSupported(portInfo.arcSupported)
@@ -1512,7 +1512,7 @@
hdmiPortInfo[i] = new HdmiPortInfo.Builder(
portInfo.portId,
portInfo.type,
- portInfo.physicalAddress)
+ Short.toUnsignedInt(portInfo.physicalAddress))
.setCecSupported(portInfo.cecSupported)
.setMhlSupported(false)
.setArcSupported(portInfo.arcSupported)
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 54e1217..d2d0279 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -304,6 +304,10 @@
// Make sure HdmiCecConfig is instantiated and the XMLs are read.
private HdmiCecConfig mHdmiCecConfig;
+ // Timeout value for start ARC action after an established eARC connection was terminated,
+ // e.g. because eARC was disabled in Settings.
+ private static final int EARC_TRIGGER_START_ARC_ACTION_DELAY = 500;
+
/**
* Interface to report send result.
*/
@@ -867,6 +871,60 @@
}
}
}, mServiceThreadExecutor);
+ mHdmiCecConfig.registerChangeListener(HdmiControlManager.CEC_SETTING_NAME_RC_PROFILE_TV,
+ new HdmiCecConfig.SettingChangeListener() {
+ @Override
+ public void onChange(String setting) {
+ reportFeatures(true);
+ }
+ },
+ mServiceThreadExecutor);
+ mHdmiCecConfig.registerChangeListener(
+ HdmiControlManager.CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_ROOT_MENU,
+ new HdmiCecConfig.SettingChangeListener() {
+ @Override
+ public void onChange(String setting) {
+ reportFeatures(false);
+ }
+ },
+ mServiceThreadExecutor);
+ mHdmiCecConfig.registerChangeListener(
+ HdmiControlManager.CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_SETUP_MENU,
+ new HdmiCecConfig.SettingChangeListener() {
+ @Override
+ public void onChange(String setting) {
+ reportFeatures(false);
+ }
+ },
+ mServiceThreadExecutor);
+ mHdmiCecConfig.registerChangeListener(
+ HdmiControlManager.CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_CONTENTS_MENU,
+ new HdmiCecConfig.SettingChangeListener() {
+ @Override
+ public void onChange(String setting) {
+ reportFeatures(false);
+ }
+ },
+ mServiceThreadExecutor);
+ mHdmiCecConfig.registerChangeListener(
+ HdmiControlManager.CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_TOP_MENU,
+ new HdmiCecConfig.SettingChangeListener() {
+ @Override
+ public void onChange(String setting) {
+ reportFeatures(false);
+ }
+ },
+ mServiceThreadExecutor);
+ mHdmiCecConfig.registerChangeListener(
+ HdmiControlManager
+ .CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_MEDIA_CONTEXT_SENSITIVE_MENU,
+ new HdmiCecConfig.SettingChangeListener() {
+ @Override
+ public void onChange(String setting) {
+ reportFeatures(false);
+ }
+ },
+ mServiceThreadExecutor);
if (isTvDevice()) {
mDeviceConfig.addOnPropertiesChangedListener(getContext().getMainExecutor(),
@@ -968,6 +1026,21 @@
}
}
+ /** Helper method for sending feature discovery command */
+ private void reportFeatures(boolean isTvDeviceSetting) {
+ // check if tv device is enabled for tv device specific RC profile setting
+ if (isTvDeviceSetting) {
+ if (isTvDeviceEnabled()) {
+ tv().reportFeatures();
+ }
+ } else { // check for source device setting
+ HdmiCecLocalDeviceSource source = isAudioSystemDevice() ? audioSystem() : playback();
+ if (source != null) {
+ source.reportFeatures();
+ }
+ }
+ }
+
/**
* Returns the initial power status used when the HdmiControlService starts.
*/
@@ -3699,7 +3772,6 @@
return mWakeUpMessageReceived;
}
- @VisibleForTesting
protected boolean isStandbyMessageReceived() {
return mStandbyMessageReceived;
}
@@ -4973,7 +5045,12 @@
// AudioService here that the eARC connection is terminated.
HdmiLogger.debug("eARC state change [new: HDMI_EARC_STATUS_ARC_PENDING(2)]");
notifyEarcStatusToAudioService(false, new ArrayList<>());
- startArcAction(true, null);
+ mHandler.postDelayed( new Runnable() {
+ @Override
+ public void run() {
+ startArcAction(true, null);
+ }
+ }, EARC_TRIGGER_START_ARC_ACTION_DELAY);
getAtomWriter().earcStatusChanged(isEarcSupported(), isEarcEnabled(),
oldEarcStatus, status, HdmiStatsEnums.LOG_REASON_EARC_STATUS_CHANGED);
} else {
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlShellCommand.java b/services/core/java/com/android/server/hdmi/HdmiControlShellCommand.java
index 8949427..bf6633e 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlShellCommand.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlShellCommand.java
@@ -124,8 +124,7 @@
return historySize(pw);
}
- getErrPrintWriter().println("Unhandled command: " + cmd);
- return 1;
+ return handleDefaultCommands(cmd);
}
private int deviceSelect(PrintWriter pw) throws RemoteException {
diff --git a/services/core/java/com/android/server/hdmi/SystemAudioInitiationActionFromAvr.java b/services/core/java/com/android/server/hdmi/SystemAudioInitiationActionFromAvr.java
index a080196..cd442c3 100644
--- a/services/core/java/com/android/server/hdmi/SystemAudioInitiationActionFromAvr.java
+++ b/services/core/java/com/android/server/hdmi/SystemAudioInitiationActionFromAvr.java
@@ -16,6 +16,7 @@
package com.android.server.hdmi;
import android.hardware.tv.cec.V1_0.SendMessageResult;
+import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
@@ -23,6 +24,7 @@
* Feature action that handles System Audio Mode initiated by AVR devices.
*/
public class SystemAudioInitiationActionFromAvr extends HdmiCecFeatureAction {
+ private static final String TAG = "SystemAudioInitiationActionFromAvr";
// State that waits for <Active Source> once send <Request Active Source>.
private static final int STATE_WAITING_FOR_ACTIVE_SOURCE = 1;
@@ -115,6 +117,10 @@
private void handleActiveSourceTimeout() {
HdmiLogger.debug("Cannot get active source.");
+ if (audioSystem().mService.isStandbyMessageReceived()) {
+ Slog.d(TAG, "Device is going to sleep, avoid to wake it up.");
+ return;
+ }
// If not able to find Active Source and the current device has playbcak functionality,
// claim Active Source and start to query TV system audio mode support.
if (audioSystem().mService.isPlaybackDevice()) {
diff --git a/services/core/java/com/android/server/infra/AbstractMasterSystemService.java b/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
index ef52d2a..e28939b 100644
--- a/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
+++ b/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
@@ -986,7 +986,7 @@
}
private void startTrackingPackageChanges() {
- final PackageMonitor monitor = new PackageMonitor() {
+ final PackageMonitor monitor = new PackageMonitor(true) {
@Override
public void onPackageUpdateStarted(@NonNull String packageName, int uid) {
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 39f3121..eb71952 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -330,6 +330,9 @@
// Manages Sticky modifier state
private final StickyModifierStateController mStickyModifierStateController;
+ // Manages Keyboard microphone mute led
+ private final KeyboardLedController mKeyboardLedController;
+
// Manages Keyboard modifier keys remapping
private final KeyRemapper mKeyRemapper;
@@ -479,6 +482,8 @@
injector.getLooper(), injector.getUEventManager())
: new KeyboardBacklightControllerInterface() {};
mStickyModifierStateController = new StickyModifierStateController();
+ mKeyboardLedController = new KeyboardLedController(mContext, injector.getLooper(),
+ mNative);
mKeyRemapper = new KeyRemapper(mContext, mNative, mDataStore, injector.getLooper());
mPointerIconCache = new PointerIconCache(mContext, mNative);
@@ -593,6 +598,7 @@
mKeyboardLayoutManager.systemRunning();
mBatteryController.systemRunning();
mKeyboardBacklightController.systemRunning();
+ mKeyboardLedController.systemRunning();
mKeyRemapper.systemRunning();
mPointerIconCache.systemRunning();
}
@@ -2218,6 +2224,7 @@
dumpDisplayInputPropertiesValues(ipw);
mBatteryController.dump(ipw);
mKeyboardBacklightController.dump(ipw);
+ mKeyboardLedController.dump(ipw);
}
private void dumpAssociations(IndentingPrintWriter pw) {
diff --git a/services/core/java/com/android/server/input/KeyboardLedController.java b/services/core/java/com/android/server/input/KeyboardLedController.java
new file mode 100644
index 0000000..5c404a2
--- /dev/null
+++ b/services/core/java/com/android/server/input/KeyboardLedController.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.input;
+
+import android.annotation.NonNull;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.graphics.Color;
+import android.hardware.SensorPrivacyManager;
+import android.hardware.SensorPrivacyManager.Sensors;
+import android.hardware.input.InputManager;
+import android.hardware.lights.Light;
+import android.media.AudioManager;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.UserHandle;
+import android.util.IndentingPrintWriter;
+import android.util.SparseArray;
+import android.view.InputDevice;
+
+import java.io.PrintWriter;
+import java.util.Objects;
+
+/**
+ * This class is used to control the light of keyboard.
+ */
+public final class KeyboardLedController implements InputManager.InputDeviceListener {
+
+ private static final String TAG = KeyboardLedController.class.getSimpleName();
+ private static final int MSG_UPDATE_EXISTING_DEVICES = 1;
+ private static final int MSG_UPDATE_MIC_MUTE_LED_STATE = 2;
+
+ private final Context mContext;
+ private final Handler mHandler;
+ private final NativeInputManagerService mNative;
+ private final SparseArray<InputDevice> mKeyboardsWithMicMuteLed = new SparseArray<>();
+ @NonNull
+ private InputManager mInputManager;
+ @NonNull
+ private SensorPrivacyManager mSensorPrivacyManager;
+ @NonNull
+ private AudioManager mAudioManager;
+ private BroadcastReceiver mMicrophoneMuteChangedIntentReceiver =
+ new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ Message msg = Message.obtain(mHandler, MSG_UPDATE_MIC_MUTE_LED_STATE);
+ mHandler.sendMessage(msg);
+ }
+ };
+
+ KeyboardLedController(Context context, Looper looper,
+ NativeInputManagerService nativeService) {
+ mContext = context;
+ mNative = nativeService;
+ mHandler = new Handler(looper, this::handleMessage);
+ }
+
+ private boolean handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_UPDATE_EXISTING_DEVICES:
+ for (int deviceId : (int[]) msg.obj) {
+ onInputDeviceAdded(deviceId);
+ }
+ return true;
+ case MSG_UPDATE_MIC_MUTE_LED_STATE:
+ updateMicMuteLedState();
+ return true;
+ }
+ return false;
+ }
+
+ private void updateMicMuteLedState() {
+ // We determine if the microphone is muted by querying both the hardware state of the
+ // microphone and the microphone sensor privacy hardware and sensor toggles
+ boolean isMicrophoneMute = mAudioManager.isMicrophoneMute()
+ || mSensorPrivacyManager.areAnySensorPrivacyTogglesEnabled(Sensors.MICROPHONE);
+ int color = isMicrophoneMute ? Color.WHITE : Color.TRANSPARENT;
+ for (int i = 0; i < mKeyboardsWithMicMuteLed.size(); i++) {
+ InputDevice device = mKeyboardsWithMicMuteLed.valueAt(i);
+ if (device != null) {
+ int deviceId = device.getId();
+ Light light = getKeyboardMicMuteLight(device);
+ if (light != null) {
+ mNative.setLightColor(deviceId, light.getId(), color);
+ }
+ }
+ }
+ }
+
+ private Light getKeyboardMicMuteLight(InputDevice device) {
+ for (Light light : device.getLightsManager().getLights()) {
+ if (light.getType() == Light.LIGHT_TYPE_KEYBOARD_MIC_MUTE
+ && light.hasBrightnessControl()) {
+ return light;
+ }
+ }
+ return null;
+ }
+
+ /** Called when the system is ready for us to start third-party code. */
+ public void systemRunning() {
+ mSensorPrivacyManager = Objects.requireNonNull(
+ mContext.getSystemService(SensorPrivacyManager.class));
+ mInputManager = Objects.requireNonNull(mContext.getSystemService(InputManager.class));
+ mAudioManager = Objects.requireNonNull(mContext.getSystemService(AudioManager.class));
+ mInputManager.registerInputDeviceListener(this, mHandler);
+ Message msg = Message.obtain(mHandler, MSG_UPDATE_EXISTING_DEVICES,
+ mInputManager.getInputDeviceIds());
+ mHandler.sendMessage(msg);
+ mContext.registerReceiverAsUser(
+ mMicrophoneMuteChangedIntentReceiver,
+ UserHandle.ALL,
+ new IntentFilter(AudioManager.ACTION_MICROPHONE_MUTE_CHANGED),
+ null,
+ mHandler);
+ }
+
+ @Override
+ public void onInputDeviceAdded(int deviceId) {
+ onInputDeviceChanged(deviceId);
+ }
+
+ @Override
+ public void onInputDeviceRemoved(int deviceId) {
+ mKeyboardsWithMicMuteLed.remove(deviceId);
+ }
+
+ @Override
+ public void onInputDeviceChanged(int deviceId) {
+ InputDevice inputDevice = mInputManager.getInputDevice(deviceId);
+ if (inputDevice == null) {
+ return;
+ }
+ if (getKeyboardMicMuteLight(inputDevice) != null) {
+ mKeyboardsWithMicMuteLed.put(deviceId, inputDevice);
+ Message msg = Message.obtain(mHandler, MSG_UPDATE_MIC_MUTE_LED_STATE);
+ mHandler.sendMessage(msg);
+ }
+ }
+
+ /** Dump the diagnostic information */
+ public void dump(PrintWriter pw) {
+ IndentingPrintWriter ipw = new IndentingPrintWriter(pw);
+ ipw.println(TAG + ": " + mKeyboardsWithMicMuteLed.size() + " keyboard mic mute lights");
+ ipw.increaseIndent();
+ for (int i = 0; i < mKeyboardsWithMicMuteLed.size(); i++) {
+ InputDevice inputDevice = mKeyboardsWithMicMuteLed.valueAt(i);
+ ipw.println(i + " " + inputDevice.getName() + ": "
+ + getKeyboardMicMuteLight(inputDevice).toString());
+ }
+ ipw.decreaseIndent();
+ }
+}
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java b/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java
index 3e23f97..b709174 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java
@@ -21,6 +21,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.UserIdInt;
import android.app.ActivityOptions;
import android.app.PendingIntent;
import android.content.ComponentName;
@@ -63,6 +64,7 @@
/** Time in milliseconds that the IME service has to bind before it is reconnected. */
static final long TIME_TO_RECONNECT = 3 * 1000;
+ @UserIdInt final int mUserId;
@NonNull private final InputMethodManagerService mService;
@NonNull private final Context mContext;
@NonNull private final PackageManagerInternal mPackageManagerInternal;
@@ -107,12 +109,15 @@
| Context.BIND_INCLUDE_CAPABILITIES
| Context.BIND_SHOWING_UI;
- InputMethodBindingController(@NonNull InputMethodManagerService service) {
- this(service, IME_CONNECTION_BIND_FLAGS, null /* latchForTesting */);
+ InputMethodBindingController(@UserIdInt int userId,
+ @NonNull InputMethodManagerService service) {
+ this(userId, service, IME_CONNECTION_BIND_FLAGS, null /* latchForTesting */);
}
- InputMethodBindingController(@NonNull InputMethodManagerService service,
- int imeConnectionBindFlags, CountDownLatch latchForTesting) {
+ InputMethodBindingController(@UserIdInt int userId,
+ @NonNull InputMethodManagerService service, int imeConnectionBindFlags,
+ CountDownLatch latchForTesting) {
+ mUserId = userId;
mService = service;
mContext = mService.mContext;
mPackageManagerInternal = mService.mPackageManagerInternal;
@@ -301,7 +306,8 @@
}
if (DEBUG) Slog.v(TAG, "Initiating attach with token: " + mCurToken);
final InputMethodInfo info =
- mService.queryInputMethodForCurrentUserLocked(mSelectedMethodId);
+ InputMethodSettingsRepository.get(mUserId).getMethodMap().get(
+ mSelectedMethodId);
boolean supportsStylusHwChanged =
mSupportsStylusHw != info.supportsStylusHandwriting();
mSupportsStylusHw = info.supportsStylusHandwriting();
@@ -339,7 +345,7 @@
private void updateCurrentMethodUid() {
final String curMethodPackage = mCurIntent.getComponent().getPackageName();
final int curMethodUid = mPackageManagerInternal.getPackageUid(
- curMethodPackage, 0 /* flags */, mService.getCurrentImeUserIdLocked());
+ curMethodPackage, 0 /* flags */, mUserId);
if (curMethodUid < 0) {
Slog.e(TAG, "Failed to get UID for package=" + curMethodPackage);
mCurMethodUid = Process.INVALID_UID;
@@ -425,7 +431,8 @@
return InputBindResult.NO_IME;
}
- InputMethodInfo info = mService.queryInputMethodForCurrentUserLocked(mSelectedMethodId);
+ InputMethodInfo info = InputMethodSettingsRepository.get(mUserId).getMethodMap().get(
+ mSelectedMethodId);
if (info == null) {
throw new IllegalArgumentException("Unknown id: " + mSelectedMethodId);
}
@@ -497,8 +504,7 @@
Slog.e(TAG, "--- bind failed: service = " + mCurIntent + ", conn = " + conn);
return false;
}
- return mContext.bindServiceAsUser(mCurIntent, conn, flags,
- new UserHandle(mService.getCurrentImeUserIdLocked()));
+ return mContext.bindServiceAsUser(mCurIntent, conn, flags, new UserHandle(mUserId));
}
@GuardedBy("ImfLock.class")
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 44a200e..0fde760 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -205,6 +205,7 @@
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.function.IntConsumer;
+import java.util.function.IntFunction;
/**
* This class provides a system service that manages input methods.
@@ -306,16 +307,17 @@
@MultiUserUnawareField
private final InputMethodMenuController mMenuController;
@MultiUserUnawareField
- @NonNull private final InputMethodBindingController mBindingController;
- @MultiUserUnawareField
- @NonNull private final AutofillSuggestionsController mAutofillController;
+ @NonNull
+ private final AutofillSuggestionsController mAutofillController;
@GuardedBy("ImfLock.class")
@MultiUserUnawareField
- @NonNull private final ImeVisibilityStateComputer mVisibilityStateComputer;
+ @NonNull
+ private final ImeVisibilityStateComputer mVisibilityStateComputer;
@GuardedBy("ImfLock.class")
- @NonNull private final DefaultImeVisibilityApplier mVisibilityApplier;
+ @NonNull
+ private final DefaultImeVisibilityApplier mVisibilityApplier;
/**
* Cache the result of {@code LocalServices.getService(AudioManagerInternal.class)}.
@@ -364,7 +366,8 @@
@MultiUserUnawareField
private int mDeviceIdToShowIme = DEVICE_ID_DEFAULT;
- @Nullable private StatusBarManagerInternal mStatusBarManagerInternal;
+ @Nullable
+ private StatusBarManagerInternal mStatusBarManagerInternal;
private boolean mShowOngoingImeSwitcherForPhones;
@GuardedBy("ImfLock.class")
@MultiUserUnawareField
@@ -382,6 +385,16 @@
@MultiUserUnawareField
Future<?> mImeDrawsImeNavBarResLazyInitFuture;
+ private final ImeTracing.ServiceDumper mDumper = new ImeTracing.ServiceDumper() {
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void dumpToProto(ProtoOutputStream proto, @Nullable byte[] icProto) {
+ dumpDebug(proto, InputMethodManagerServiceTraceProto.INPUT_METHOD_MANAGER_SERVICE);
+ }
+ };
+
static class SessionState {
final ClientState mClient;
final IInputMethodInvoker mMethod;
@@ -468,12 +481,8 @@
@GuardedBy("ImfLock.class")
@Nullable
String getSelectedMethodIdLocked() {
- return mBindingController.getSelectedMethodId();
- }
-
- @GuardedBy("ImfLock.class")
- private void setSelectedMethodIdLocked(@Nullable String selectedMethodId) {
- mBindingController.setSelectedMethodId(selectedMethodId);
+ final var userData = mUserDataRepository.getOrCreate(mCurrentUserId);
+ return userData.mBindingController.getSelectedMethodId();
}
/**
@@ -482,7 +491,8 @@
*/
@GuardedBy("ImfLock.class")
private int getSequenceNumberLocked() {
- return mBindingController.getSequenceNumber();
+ final var userData = mUserDataRepository.getOrCreate(mCurrentUserId);
+ return userData.mBindingController.getSequenceNumber();
}
/**
@@ -491,7 +501,8 @@
*/
@GuardedBy("ImfLock.class")
private void advanceSequenceNumberLocked() {
- mBindingController.advanceSequenceNumber();
+ final var userData = mUserDataRepository.getOrCreate(mCurrentUserId);
+ userData.mBindingController.advanceSequenceNumber();
}
@GuardedBy("ImfLock.class")
@@ -531,7 +542,8 @@
* The {@link IRemoteAccessibilityInputConnection} last provided by the current client.
*/
@MultiUserUnawareField
- @Nullable IRemoteAccessibilityInputConnection mCurRemoteAccessibilityInputConnection;
+ @Nullable
+ IRemoteAccessibilityInputConnection mCurRemoteAccessibilityInputConnection;
/**
* The {@link EditorInfo} last provided by the current client.
@@ -551,7 +563,8 @@
@GuardedBy("ImfLock.class")
@Nullable
private String getCurIdLocked() {
- return mBindingController.getCurId();
+ final var userData = mUserDataRepository.getOrCreate(mCurrentUserId);
+ return userData.mBindingController.getCurId();
}
/**
@@ -575,7 +588,8 @@
*/
@GuardedBy("ImfLock.class")
private boolean hasConnectionLocked() {
- return mBindingController.hasMainConnection();
+ final var userData = mUserDataRepository.getOrCreate(mCurrentUserId);
+ return userData.mBindingController.hasMainConnection();
}
/**
@@ -598,7 +612,8 @@
@GuardedBy("ImfLock.class")
@Nullable
private Intent getCurIntentLocked() {
- return mBindingController.getCurIntent();
+ final var userData = mUserDataRepository.getOrCreate(mCurrentUserId);
+ return userData.mBindingController.getCurIntent();
}
/**
@@ -608,7 +623,8 @@
@GuardedBy("ImfLock.class")
@Nullable
IBinder getCurTokenLocked() {
- return mBindingController.getCurToken();
+ final var userData = mUserDataRepository.getOrCreate(mCurrentUserId);
+ return userData.mBindingController.getCurToken();
}
/**
@@ -649,7 +665,8 @@
@GuardedBy("ImfLock.class")
@Nullable
IInputMethodInvoker getCurMethodLocked() {
- return mBindingController.getCurMethod();
+ final var userData = mUserDataRepository.getOrCreate(mCurrentUserId);
+ return userData.mBindingController.getCurMethod();
}
/**
@@ -657,7 +674,8 @@
*/
@GuardedBy("ImfLock.class")
private int getCurMethodUidLocked() {
- return mBindingController.getCurMethodUid();
+ final var userData = mUserDataRepository.getOrCreate(mCurrentUserId);
+ return userData.mBindingController.getCurMethodUid();
}
/**
@@ -666,7 +684,8 @@
*/
@GuardedBy("ImfLock.class")
private long getLastBindTimeLocked() {
- return mBindingController.getLastBindTime();
+ final var userData = mUserDataRepository.getOrCreate(mCurrentUserId);
+ return userData.mBindingController.getLastBindTime();
}
/**
@@ -790,7 +809,8 @@
mRegistered = true;
}
- @Override public void onChange(boolean selfChange, Uri uri) {
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
final Uri showImeUri = Settings.Secure.getUriFor(
Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD);
final Uri accessibilityRequestingNoImeUri = Settings.Secure.getUriFor(
@@ -816,6 +836,8 @@
}
} else if (stylusHandwritingEnabledUri.equals(uri)) {
InputMethodManager.invalidateLocalStylusHandwritingAvailabilityCaches();
+ InputMethodManager
+ .invalidateLocalConnectionlessStylusHandwritingAvailabilityCaches();
} else {
boolean enabledChanged = false;
String newEnabled = InputMethodSettingsRepository.get(mCurrentUserId)
@@ -881,10 +903,10 @@
}
for (int userId : mUserManagerInternal.getUserIds()) {
final InputMethodSettings settings = queryInputMethodServicesInternal(
- mContext,
- userId,
- AdditionalSubtypeMapRepository.get(userId),
- DirectBootAwareness.AUTO);
+ mContext,
+ userId,
+ AdditionalSubtypeMapRepository.get(userId),
+ DirectBootAwareness.AUTO);
InputMethodSettingsRepository.put(userId, settings);
}
postInputMethodSettingUpdatedLocked(true /* resetDefaultEnabledIme */);
@@ -934,6 +956,10 @@
*/
private ArrayList<String> mDataClearedPackages = new ArrayList<>();
+ private MyPackageMonitor() {
+ super(true);
+ }
+
@GuardedBy("ImfLock.class")
void clearKnownImePackageNamesLocked() {
mKnownImePackageNames.clear();
@@ -1342,7 +1368,7 @@
InputMethodManagerService(
Context context,
@Nullable ServiceThread serviceThreadForTesting,
- @Nullable InputMethodBindingController bindingControllerForTesting) {
+ @Nullable IntFunction<InputMethodBindingController> bindingControllerForTesting) {
synchronized (ImfLock.class) {
mContext = context;
mRes = context.getResources();
@@ -1381,7 +1407,12 @@
AdditionalSubtypeMapRepository.initialize(mHandler, mContext);
mCurrentUserId = mActivityManagerInternal.getCurrentUserId();
- mUserDataRepository = new UserDataRepository(mHandler, mUserManagerInternal);
+ @SuppressWarnings("GuardedBy") final IntFunction<InputMethodBindingController>
+ bindingControllerFactory = userId -> new InputMethodBindingController(userId,
+ InputMethodManagerService.this);
+ mUserDataRepository = new UserDataRepository(mHandler, mUserManagerInternal,
+ bindingControllerForTesting != null ? bindingControllerForTesting
+ : bindingControllerFactory);
for (int id : mUserManagerInternal.getUserIds()) {
mUserDataRepository.getOrCreate(id);
}
@@ -1395,12 +1426,7 @@
new HardwareKeyboardShortcutController(settings.getMethodMap(),
settings.getUserId());
mMenuController = new InputMethodMenuController(this);
- mBindingController =
- bindingControllerForTesting != null
- ? bindingControllerForTesting
- : new InputMethodBindingController(this);
mAutofillController = new AutofillSuggestionsController(this);
-
mVisibilityStateComputer = new ImeVisibilityStateComputer(this);
mVisibilityApplier = new DefaultImeVisibilityApplier(this);
@@ -1526,6 +1552,20 @@
+ " currentUserId=" + mCurrentUserId);
}
+ // Clean up stuff for mCurrentUserId, which soon becomes the previous user.
+
+ // TODO(b/338461930): Check if this is still necessary or not.
+ onUnbindCurrentMethodByReset();
+
+ // Note that in b/197848765 we want to see if we can keep the binding alive for better
+ // profile switching.
+ final var userData = mUserDataRepository.getOrCreate(mCurrentUserId);
+ userData.mBindingController.unbindCurrentMethod();
+
+ unbindCurrentClientLocked(UnbindReason.SWITCH_USER);
+
+ // Hereafter we start initializing things for "newUserId".
+
maybeInitImeNavbarConfigLocked(newUserId);
// ContentObserver should be registered again when the user is changed
@@ -1547,10 +1587,6 @@
// IME for that user.
final boolean initialUserSwitch = TextUtils.isEmpty(defaultImiId);
- // The mSystemReady flag is set during boot phase,
- // and user switch would not happen at that time.
- resetCurrentMethodAndClientLocked(UnbindReason.SWITCH_USER);
-
final InputMethodSettings newSettings = InputMethodSettingsRepository.get(newUserId);
postInputMethodSettingUpdatedLocked(initialUserSwitch /* resetDefaultEnabledIme */);
if (TextUtils.isEmpty(newSettings.getSelectedInputMethod())) {
@@ -1742,9 +1778,10 @@
// Check if selected IME of current user supports handwriting.
if (userId == mCurrentUserId) {
- return mBindingController.supportsStylusHandwriting()
+ final var userData = mUserDataRepository.getOrCreate(userId);
+ return userData.mBindingController.supportsStylusHandwriting()
&& (!connectionless
- || mBindingController.supportsConnectionlessStylusHandwriting());
+ || userData.mBindingController.supportsConnectionlessStylusHandwriting());
}
final InputMethodSettings settings = InputMethodSettingsRepository.get(userId);
final InputMethodInfo imi = settings.getMethodMap().get(
@@ -2074,7 +2111,8 @@
curInputMethodInfo != null && curInputMethodInfo.suppressesSpellChecker();
final SparseArray<IAccessibilityInputMethodSession> accessibilityInputMethodSessions =
createAccessibilityInputMethodSessions(mCurClient.mAccessibilitySessions);
- if (mBindingController.supportsStylusHandwriting() && hasSupportedStylusLocked()) {
+ final var userData = mUserDataRepository.getOrCreate(mCurrentUserId);
+ if (userData.mBindingController.supportsStylusHandwriting() && hasSupportedStylusLocked()) {
mHwController.setInkWindowInitializer(new InkWindowInitializer());
}
return new InputBindResult(InputBindResult.ResultCode.SUCCESS_WITH_IME_SESSION,
@@ -2195,6 +2233,8 @@
if (connectionIsActive != connectionWasActive) {
mInputManagerInternal.notifyInputMethodConnectionActive(connectionIsActive);
}
+ final var userData = mUserDataRepository.getOrCreate(mCurrentUserId);
+ final var bindingController = userData.mBindingController;
// If configured, we want to avoid starting up the IME if it is not supposed to be showing
if (shouldPreventImeStartupLocked(selectedMethodId, startInputFlags,
@@ -2203,7 +2243,7 @@
Slog.d(TAG, "Avoiding IME startup and unbinding current input method.");
}
invalidateAutofillSessionLocked();
- mBindingController.unbindCurrentMethod();
+ bindingController.unbindCurrentMethod();
return InputBindResult.NO_EDITOR;
}
@@ -2235,9 +2275,8 @@
}
}
- mBindingController.unbindCurrentMethod();
-
- return mBindingController.bindCurrentMethod();
+ bindingController.unbindCurrentMethod();
+ return bindingController.bindCurrentMethod();
}
/**
@@ -2383,7 +2422,8 @@
@FunctionalInterface
interface ImeDisplayValidator {
- @DisplayImePolicy int getDisplayImePolicy(int displayId);
+ @DisplayImePolicy
+ int getDisplayImePolicy(int displayId);
}
/**
@@ -2497,10 +2537,13 @@
@GuardedBy("ImfLock.class")
void resetCurrentMethodAndClientLocked(@UnbindReason int unbindClientReason) {
- setSelectedMethodIdLocked(null);
+ final var userData = mUserDataRepository.getOrCreate(mCurrentUserId);
+ userData.mBindingController.setSelectedMethodId(null);
+
// Callback before clean-up binding states.
+ // TODO(b/338461930): Check if this is still necessary or not.
onUnbindCurrentMethodByReset();
- mBindingController.unbindCurrentMethod();
+ userData.mBindingController.unbindCurrentMethod();
unbindCurrentClientLocked(unbindClientReason);
}
@@ -2675,7 +2718,7 @@
: null;
if (mStatusBarManagerInternal != null) {
mStatusBarManagerInternal.setIcon(mSlotIme, packageName, iconId, 0,
- contentDescription != null
+ contentDescription != null
? contentDescription.toString() : null);
mStatusBarManagerInternal.setIconVisibility(mSlotIme, true);
}
@@ -3077,7 +3120,8 @@
// mCurMethodId should be updated after setSelectedInputMethodAndSubtypeLocked()
// because mCurMethodId is stored as a history in
// setSelectedInputMethodAndSubtypeLocked().
- setSelectedMethodIdLocked(id);
+ final var userData = mUserDataRepository.getOrCreate(mCurrentUserId);
+ userData.mBindingController.setSelectedMethodId(id);
if (mActivityManagerInternal.isSystemReady()) {
Intent intent = new Intent(Intent.ACTION_INPUT_METHOD_CHANGED);
@@ -3099,7 +3143,7 @@
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.showSoftInput");
int uid = Binder.getCallingUid();
ImeTracing.getInstance().triggerManagerServiceDump(
- "InputMethodManagerService#showSoftInput");
+ "InputMethodManagerService#showSoftInput", mDumper);
synchronized (ImfLock.class) {
if (!canInteractWithImeLocked(uid, client, "showSoftInput", statsToken)) {
ImeTracker.forLogging().onFailed(
@@ -3132,7 +3176,8 @@
@Nullable String delegatorPackageName,
@NonNull IConnectionlessHandwritingCallback callback) {
synchronized (ImfLock.class) {
- if (!mBindingController.supportsConnectionlessStylusHandwriting()) {
+ final var userData = mUserDataRepository.getOrCreate(userId);
+ if (!userData.mBindingController.supportsConnectionlessStylusHandwriting()) {
Slog.w(TAG, "Connectionless stylus handwriting mode unsupported by IME.");
try {
callback.onError(CONNECTIONLESS_HANDWRITING_ERROR_UNSUPPORTED);
@@ -3198,7 +3243,7 @@
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.startStylusHandwriting");
try {
ImeTracing.getInstance().triggerManagerServiceDump(
- "InputMethodManagerService#startStylusHandwriting");
+ "InputMethodManagerService#startStylusHandwriting", mDumper);
int uid = Binder.getCallingUid();
synchronized (ImfLock.class) {
if (!acceptingDelegation) {
@@ -3215,7 +3260,8 @@
}
final long ident = Binder.clearCallingIdentity();
try {
- if (!mBindingController.supportsStylusHandwriting()) {
+ final var userData = mUserDataRepository.getOrCreate(mCurrentUserId);
+ if (!userData.mBindingController.supportsStylusHandwriting()) {
Slog.w(TAG,
"Stylus HW unsupported by IME. Ignoring startStylusHandwriting()");
return false;
@@ -3398,10 +3444,18 @@
mVisibilityStateComputer.requestImeVisibility(windowToken, true);
// Ensure binding the connection when IME is going to show.
- mBindingController.setCurrentMethodVisible();
+ final var userData = mUserDataRepository.getOrCreate(mCurrentUserId);
+ userData.mBindingController.setCurrentMethodVisible();
final IInputMethodInvoker curMethod = getCurMethodLocked();
ImeTracker.forLogging().onCancelled(mCurStatsToken, ImeTracker.PHASE_SERVER_WAIT_IME);
- if (curMethod != null) {
+ final boolean readyToDispatchToIme;
+ if (Flags.deferShowSoftInputUntilSessionCreation()) {
+ readyToDispatchToIme =
+ curMethod != null && mCurClient != null && mCurClient.mCurSession != null;
+ } else {
+ readyToDispatchToIme = curMethod != null;
+ }
+ if (readyToDispatchToIme) {
ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_SERVER_HAS_IME);
mCurStatsToken = null;
@@ -3426,7 +3480,7 @@
ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {
int uid = Binder.getCallingUid();
ImeTracing.getInstance().triggerManagerServiceDump(
- "InputMethodManagerService#hideSoftInput");
+ "InputMethodManagerService#hideSoftInput", mDumper);
synchronized (ImfLock.class) {
if (!canInteractWithImeLocked(uid, client, "hideSoftInput", statsToken)) {
if (isInputShownLocked()) {
@@ -3499,7 +3553,8 @@
} else {
ImeTracker.forLogging().onCancelled(statsToken, ImeTracker.PHASE_SERVER_SHOULD_HIDE);
}
- mBindingController.setCurrentMethodNotVisible();
+ final var userData = mUserDataRepository.getOrCreate(mCurrentUserId);
+ userData.mBindingController.setCurrentMethodNotVisible();
mVisibilityStateComputer.clearImeShowFlags();
// Cancel existing statsToken for show IME as we got a hide request.
ImeTracker.forLogging().onCancelled(mCurStatsToken, ImeTracker.PHASE_SERVER_WAIT_IME);
@@ -3564,7 +3619,7 @@
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER,
"IMMS.startInputOrWindowGainedFocus");
ImeTracing.getInstance().triggerManagerServiceDump(
- "InputMethodManagerService#startInputOrWindowGainedFocus");
+ "InputMethodManagerService#startInputOrWindowGainedFocus", mDumper);
final InputBindResult result;
synchronized (ImfLock.class) {
// If the system is not yet ready, we shouldn't be running third party code.
@@ -3781,7 +3836,8 @@
// Note that we can trust client's display ID as long as it matches
// to the display ID obtained from the window.
if (cs.mSelfReportedDisplayId != mCurTokenDisplayId) {
- mBindingController.unbindCurrentMethod();
+ final var userData = mUserDataRepository.getOrCreate(userId);
+ userData.mBindingController.unbindCurrentMethod();
}
}
}
@@ -4242,8 +4298,9 @@
mStylusIds.add(deviceId);
// a new Stylus is detected. If IME supports handwriting, and we don't have
// handwriting initialized, lets do it now.
+ final var userData = mUserDataRepository.getOrCreate(mCurrentUserId);
if (!mHwController.getCurrentRequestId().isPresent()
- && mBindingController.supportsStylusHandwriting()) {
+ && userData.mBindingController.supportsStylusHandwriting()) {
scheduleResetStylusHandwriting();
}
}
@@ -4655,7 +4712,7 @@
SparseArray<IAccessibilityInputMethodSession> disabledSessions = new SparseArray<>();
for (int i = 0; i < mEnabledAccessibilitySessions.size(); i++) {
if (!accessibilitySessions.contains(mEnabledAccessibilitySessions.keyAt(i))) {
- AccessibilitySessionState sessionState = mEnabledAccessibilitySessions.valueAt(i);
+ AccessibilitySessionState sessionState = mEnabledAccessibilitySessions.valueAt(i);
if (sessionState != null) {
disabledSessions.append(mEnabledAccessibilitySessions.keyAt(i),
sessionState.mSession);
@@ -4812,7 +4869,8 @@
case MSG_RESET_HANDWRITING: {
synchronized (ImfLock.class) {
- if (mBindingController.supportsStylusHandwriting()
+ final var userData = mUserDataRepository.getOrCreate(mCurrentUserId);
+ if (userData.mBindingController.supportsStylusHandwriting()
&& getCurMethodLocked() != null && hasSupportedStylusLocked()) {
Slog.d(TAG, "Initializing Handwriting Spy");
mHwController.initializeHandwritingSpy(mCurTokenDisplayId);
@@ -4837,11 +4895,12 @@
if (curMethod == null || mImeBindingState.mFocusedWindow == null) {
return true;
}
+ final var userData = mUserDataRepository.getOrCreate(mCurrentUserId);
final HandwritingModeController.HandwritingSession session =
mHwController.startHandwritingSession(
msg.arg1 /*requestId*/,
msg.arg2 /*pid*/,
- mBindingController.getCurMethodUid(),
+ userData.mBindingController.getCurMethodUid(),
mImeBindingState.mFocusedWindow);
if (session == null) {
Slog.e(TAG,
@@ -5135,7 +5194,8 @@
@GuardedBy("ImfLock.class")
void sendOnNavButtonFlagsChangedLocked() {
- final IInputMethodInvoker curMethod = mBindingController.getCurMethod();
+ final var userData = mUserDataRepository.getOrCreate(mCurrentUserId);
+ final IInputMethodInvoker curMethod = userData.mBindingController.getCurMethod();
if (curMethod == null) {
// No need to send the data if the IME is not yet bound.
return;
@@ -5387,7 +5447,7 @@
}
if (!settings.getMethodMap().containsKey(imeId)
|| !settings.getEnabledInputMethodList().contains(
- settings.getMethodMap().get(imeId))) {
+ settings.getMethodMap().get(imeId))) {
return false; // IME is not found or not enabled.
}
settings.putSelectedInputMethod(imeId);
@@ -5888,9 +5948,10 @@
p.println(" mCurClient=" + client + " mCurSeq=" + getSequenceNumberLocked());
p.println(" mFocusedWindowPerceptible=" + mFocusedWindowPerceptible);
mImeBindingState.dump(" ", p);
+ final var userData = mUserDataRepository.getOrCreate(mCurrentUserId);
p.println(" mCurId=" + getCurIdLocked() + " mHaveConnection=" + hasConnectionLocked()
+ " mBoundToMethod=" + mBoundToMethod + " mVisibleBound="
- + mBindingController.isVisibleBound());
+ + userData.mBindingController.isVisibleBound());
p.println(" mCurToken=" + getCurTokenLocked());
p.println(" mCurTokenDisplayId=" + mCurTokenDisplayId);
p.println(" mCurHostInputToken=" + mCurHostInputToken);
@@ -6384,7 +6445,8 @@
if (userId == mCurrentUserId) {
hideCurrentInputLocked(mImeBindingState.mFocusedWindow, 0 /* flags */,
SoftInputShowHideReason.HIDE_RESET_SHELL_COMMAND);
- mBindingController.unbindCurrentMethod();
+ final var userData = mUserDataRepository.getOrCreate(userId);
+ userData.mBindingController.unbindCurrentMethod();
// Enable default IMEs, disable others
var toDisable = settings.getEnabledInputMethodList();
@@ -6528,6 +6590,7 @@
private final InputMethodManagerService mImms;
@NonNull
private final IBinder mToken;
+
InputMethodPrivilegedOperationsImpl(InputMethodManagerService imms,
@NonNull IBinder token) {
mImms = imms;
@@ -6556,8 +6619,7 @@
@Override
public void createInputContentUriToken(Uri contentUri, String packageName,
AndroidFuture future /* T=IBinder */) {
- @SuppressWarnings("unchecked")
- final AndroidFuture<IBinder> typedFuture = future;
+ @SuppressWarnings("unchecked") final AndroidFuture<IBinder> typedFuture = future;
try {
typedFuture.complete(mImms.createInputContentUriToken(
mToken, contentUri, packageName).asBinder());
@@ -6575,8 +6637,7 @@
@BinderThread
@Override
public void setInputMethod(String id, AndroidFuture future /* T=Void */) {
- @SuppressWarnings("unchecked")
- final AndroidFuture<Void> typedFuture = future;
+ @SuppressWarnings("unchecked") final AndroidFuture<Void> typedFuture = future;
try {
mImms.setInputMethod(mToken, id);
typedFuture.complete(null);
@@ -6589,8 +6650,7 @@
@Override
public void setInputMethodAndSubtype(String id, InputMethodSubtype subtype,
AndroidFuture future /* T=Void */) {
- @SuppressWarnings("unchecked")
- final AndroidFuture<Void> typedFuture = future;
+ @SuppressWarnings("unchecked") final AndroidFuture<Void> typedFuture = future;
try {
mImms.setInputMethodAndSubtype(mToken, id, subtype);
typedFuture.complete(null);
@@ -6604,8 +6664,7 @@
public void hideMySoftInput(@NonNull ImeTracker.Token statsToken,
@InputMethodManager.HideFlags int flags, @SoftInputShowHideReason int reason,
AndroidFuture future /* T=Void */) {
- @SuppressWarnings("unchecked")
- final AndroidFuture<Void> typedFuture = future;
+ @SuppressWarnings("unchecked") final AndroidFuture<Void> typedFuture = future;
try {
mImms.hideMySoftInput(mToken, statsToken, flags, reason);
typedFuture.complete(null);
@@ -6619,8 +6678,7 @@
public void showMySoftInput(@NonNull ImeTracker.Token statsToken,
@InputMethodManager.ShowFlags int flags, @SoftInputShowHideReason int reason,
AndroidFuture future /* T=Void */) {
- @SuppressWarnings("unchecked")
- final AndroidFuture<Void> typedFuture = future;
+ @SuppressWarnings("unchecked") final AndroidFuture<Void> typedFuture = future;
try {
mImms.showMySoftInput(mToken, statsToken, flags, reason);
typedFuture.complete(null);
@@ -6638,8 +6696,7 @@
@BinderThread
@Override
public void switchToPreviousInputMethod(AndroidFuture future /* T=Boolean */) {
- @SuppressWarnings("unchecked")
- final AndroidFuture<Boolean> typedFuture = future;
+ @SuppressWarnings("unchecked") final AndroidFuture<Boolean> typedFuture = future;
try {
typedFuture.complete(mImms.switchToPreviousInputMethod(mToken));
} catch (Throwable e) {
@@ -6651,8 +6708,7 @@
@Override
public void switchToNextInputMethod(boolean onlyCurrentIme,
AndroidFuture future /* T=Boolean */) {
- @SuppressWarnings("unchecked")
- final AndroidFuture<Boolean> typedFuture = future;
+ @SuppressWarnings("unchecked") final AndroidFuture<Boolean> typedFuture = future;
try {
typedFuture.complete(mImms.switchToNextInputMethod(mToken, onlyCurrentIme));
} catch (Throwable e) {
@@ -6663,8 +6719,7 @@
@BinderThread
@Override
public void shouldOfferSwitchingToNextInputMethod(AndroidFuture future /* T=Boolean */) {
- @SuppressWarnings("unchecked")
- final AndroidFuture<Boolean> typedFuture = future;
+ @SuppressWarnings("unchecked") final AndroidFuture<Boolean> typedFuture = future;
try {
typedFuture.complete(mImms.shouldOfferSwitchingToNextInputMethod(mToken));
} catch (Throwable e) {
diff --git a/services/core/java/com/android/server/inputmethod/UserDataRepository.java b/services/core/java/com/android/server/inputmethod/UserDataRepository.java
index 7f00229..825cfcb 100644
--- a/services/core/java/com/android/server/inputmethod/UserDataRepository.java
+++ b/services/core/java/com/android/server/inputmethod/UserDataRepository.java
@@ -15,6 +15,7 @@
*/
package com.android.server.inputmethod;
+
import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.content.pm.UserInfo;
@@ -25,18 +26,21 @@
import com.android.server.pm.UserManagerInternal;
import java.util.function.Consumer;
+import java.util.function.IntFunction;
final class UserDataRepository {
@GuardedBy("ImfLock.class")
private final SparseArray<UserData> mUserData = new SparseArray<>();
+ private final IntFunction<InputMethodBindingController> mBindingControllerFactory;
+
@GuardedBy("ImfLock.class")
@NonNull
UserData getOrCreate(@UserIdInt int userId) {
UserData userData = mUserData.get(userId);
if (userData == null) {
- userData = new UserData(userId);
+ userData = new UserData(userId, mBindingControllerFactory.apply(userId));
mUserData.put(userId, userData);
}
return userData;
@@ -49,7 +53,9 @@
}
}
- UserDataRepository(@NonNull Handler handler, @NonNull UserManagerInternal userManagerInternal) {
+ UserDataRepository(@NonNull Handler handler, @NonNull UserManagerInternal userManagerInternal,
+ @NonNull IntFunction<InputMethodBindingController> bindingControllerFactory) {
+ mBindingControllerFactory = bindingControllerFactory;
userManagerInternal.addUserLifecycleListener(
new UserManagerInternal.UserLifecycleListener() {
@Override
@@ -79,11 +85,16 @@
@UserIdInt
final int mUserId;
- /**
+ @NonNull
+ final InputMethodBindingController mBindingController;
+
+ /**
* Intended to be instantiated only from this file.
*/
- private UserData(@UserIdInt int userId) {
+ private UserData(@UserIdInt int userId,
+ @NonNull InputMethodBindingController bindingController) {
mUserId = userId;
+ mBindingController = bindingController;
}
}
}
diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubService.java b/services/core/java/com/android/server/location/contexthub/ContextHubService.java
index 5731161..d6d134d 100644
--- a/services/core/java/com/android/server/location/contexthub/ContextHubService.java
+++ b/services/core/java/com/android/server/location/contexthub/ContextHubService.java
@@ -78,10 +78,14 @@
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.Optional;
+import java.util.PriorityQueue;
+import java.util.Random;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
/**
@@ -152,6 +156,16 @@
private final ScheduledThreadPoolExecutor mDailyMetricTimer =
new ScheduledThreadPoolExecutor(1);
+ // A queue of reliable message records for duplicate detection
+ private final PriorityQueue<ReliableMessageRecord> mReliableMessageRecordQueue =
+ new PriorityQueue<ReliableMessageRecord>(
+ (ReliableMessageRecord left, ReliableMessageRecord right) -> {
+ return Long.compare(left.getTimestamp(), right.getTimestamp());
+ });
+
+ // The test mode manager that manages behaviors during test mode.
+ private final TestModeManager mTestModeManager = new TestModeManager();
+
// The period of the recurring time
private static final int PERIOD_METRIC_QUERY_DAYS = 1;
@@ -164,6 +178,9 @@
private boolean mIsBtScanningEnabled = false;
private boolean mIsBtMainEnabled = false;
+ // True if test mode is enabled for the Context Hub
+ private AtomicBoolean mIsTestModeEnabled = new AtomicBoolean(false);
+
// A hashmap used to record if a contexthub is waiting for daily query
private Set<Integer> mMetricQueryPendingContextHubIds =
Collections.newSetFromMap(new ConcurrentHashMap<Integer, Boolean>());
@@ -210,8 +227,17 @@
@Override
public void handleNanoappMessage(short hostEndpointId, NanoAppMessage message,
List<String> nanoappPermissions, List<String> messagePermissions) {
- handleClientMessageCallback(mContextHubId, hostEndpointId, message, nanoappPermissions,
- messagePermissions);
+ if (Flags.reliableMessageImplementation()
+ && Flags.reliableMessageTestModeBehavior()
+ && mIsTestModeEnabled.get()
+ && mTestModeManager.handleNanoappMessage(mContextHubId, hostEndpointId,
+ message, nanoappPermissions, messagePermissions)) {
+ // The TestModeManager handled the nanoapp message, so return here.
+ return;
+ }
+
+ handleClientMessageCallback(mContextHubId, hostEndpointId, message,
+ nanoappPermissions, messagePermissions);
}
@Override
@@ -228,6 +254,106 @@
}
}
+ /**
+ * Records a reliable message from a nanoapp for duplicate detection.
+ */
+ private static class ReliableMessageRecord {
+ public static final int TIMEOUT_NS = 1000000000;
+
+ public int mContextHubId;
+ public long mTimestamp;
+ public int mMessageSequenceNumber;
+ byte mErrorCode;
+
+ ReliableMessageRecord(int contextHubId, long timestamp,
+ int messageSequenceNumber, byte errorCode) {
+ mContextHubId = contextHubId;
+ mTimestamp = timestamp;
+ mMessageSequenceNumber = messageSequenceNumber;
+ mErrorCode = errorCode;
+ }
+
+ public int getContextHubId() {
+ return mContextHubId;
+ }
+
+ public long getTimestamp() {
+ return mTimestamp;
+ }
+
+ public int getMessageSequenceNumber() {
+ return mMessageSequenceNumber;
+ }
+
+ public byte getErrorCode() {
+ return mErrorCode;
+ }
+
+ public void setErrorCode(byte errorCode) {
+ mErrorCode = errorCode;
+ }
+
+ public boolean isExpired() {
+ return mTimestamp + TIMEOUT_NS < SystemClock.elapsedRealtimeNanos();
+ }
+ }
+
+ /**
+ * A class to manage behaviors during test mode. This is used for testing.
+ */
+ private class TestModeManager {
+ /**
+ * Probability (in percent) of duplicating a message.
+ */
+ private static final int MESSAGE_DUPLICATION_PROBABILITY_PERCENT = 50;
+
+ /**
+ * The number of total messages to send when the duplicate event happens.
+ */
+ private static final int NUM_MESSAGES_TO_DUPLICATE = 3;
+
+ /**
+ * A probability percent for a certain event.
+ */
+ private static final int MAX_PROBABILITY_PERCENT = 100;
+
+ /**
+ * Random number generator.
+ */
+ private Random mRandom = new Random();
+
+ /**
+ * @see ContextHubServiceCallback.handleNanoappMessage
+ * @return whether the message was handled
+ */
+ public boolean handleNanoappMessage(int contextHubId,
+ short hostEndpointId, NanoAppMessage message,
+ List<String> nanoappPermissions, List<String> messagePermissions) {
+ if (!message.isReliable()) {
+ return false;
+ }
+
+ if (didEventHappen(MESSAGE_DUPLICATION_PROBABILITY_PERCENT)) {
+ for (int i = 0; i < NUM_MESSAGES_TO_DUPLICATE; ++i) {
+ handleClientMessageCallback(contextHubId, hostEndpointId,
+ message, nanoappPermissions, messagePermissions);
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Returns true if the event with percentPercent did happen.
+ *
+ * @param probabilityPercent the percent probability of the event.
+ * @return true if the event happened, false otherwise.
+ */
+ private boolean didEventHappen(int probabilityPercent) {
+ return mRandom.nextInt(MAX_PROBABILITY_PERCENT) < probabilityPercent;
+ }
+ }
+
public ContextHubService(Context context, IContextHubWrapper contextHubWrapper) {
Log.i(TAG, "Starting Context Hub Service init");
mContext = context;
@@ -563,6 +689,8 @@
* Resets the settings. Called when a context hub restarts or the AIDL HAL dies
*/
private void resetSettings() {
+ mIsTestModeEnabled.set(false);
+
sendLocationSettingUpdate();
sendWifiSettingUpdate(/* forceUpdate= */ true);
sendAirplaneModeSettingUpdate();
@@ -854,14 +982,76 @@
private void handleClientMessageCallback(int contextHubId, short hostEndpointId,
NanoAppMessage message, List<String> nanoappPermissions,
List<String> messagePermissions) {
- byte errorCode = mClientManager.onMessageFromNanoApp(contextHubId, hostEndpointId, message,
- nanoappPermissions, messagePermissions);
- if (message.isReliable() && errorCode != ErrorCode.OK) {
- sendMessageDeliveryStatusToContextHub(contextHubId, message.getMessageSequenceNumber(),
- errorCode);
+ if (!Flags.reliableMessageImplementation()
+ || !Flags.reliableMessageDuplicateDetectionService()) {
+ byte errorCode = mClientManager.onMessageFromNanoApp(contextHubId, hostEndpointId,
+ message, nanoappPermissions, messagePermissions);
+ if (message.isReliable() && errorCode != ErrorCode.OK) {
+ sendMessageDeliveryStatusToContextHub(contextHubId,
+ message.getMessageSequenceNumber(), errorCode);
+ }
+ return;
+ }
+
+ if (message.isReliable()) {
+ byte errorCode = ErrorCode.OK;
+ synchronized (mReliableMessageRecordQueue) {
+ Optional<ReliableMessageRecord> record = Optional.empty();
+ for (ReliableMessageRecord r: mReliableMessageRecordQueue) {
+ if (r.getContextHubId() == contextHubId
+ && r.getMessageSequenceNumber() == message.getMessageSequenceNumber()) {
+ record = Optional.of(r);
+ break;
+ }
+ }
+
+ if (record.isPresent()) {
+ errorCode = record.get().getErrorCode();
+ if (errorCode == ErrorCode.TRANSIENT_ERROR) {
+ Log.w(TAG, "Found duplicate reliable message with message sequence number: "
+ + record.get().getMessageSequenceNumber() + ": retrying");
+ errorCode = mClientManager.onMessageFromNanoApp(
+ contextHubId, hostEndpointId, message,
+ nanoappPermissions, messagePermissions);
+ record.get().setErrorCode(errorCode);
+ } else {
+ Log.w(TAG, "Found duplicate reliable message with message sequence number: "
+ + record.get().getMessageSequenceNumber());
+ }
+ } else {
+ errorCode = mClientManager.onMessageFromNanoApp(
+ contextHubId, hostEndpointId, message,
+ nanoappPermissions, messagePermissions);
+ mReliableMessageRecordQueue.add(
+ new ReliableMessageRecord(contextHubId,
+ SystemClock.elapsedRealtimeNanos(),
+ message.getMessageSequenceNumber(),
+ errorCode));
+ }
+ }
+ sendMessageDeliveryStatusToContextHub(contextHubId,
+ message.getMessageSequenceNumber(), errorCode);
+ } else {
+ mClientManager.onMessageFromNanoApp(
+ contextHubId, hostEndpointId, message,
+ nanoappPermissions, messagePermissions);
+ }
+
+ synchronized (mReliableMessageRecordQueue) {
+ while (mReliableMessageRecordQueue.peek() != null
+ && mReliableMessageRecordQueue.peek().isExpired()) {
+ mReliableMessageRecordQueue.poll();
+ }
}
}
+ /**
+ * Sends the message delivery status to the Context Hub.
+ *
+ * @param contextHubId the ID of the hub
+ * @param messageSequenceNumber the message sequence number
+ * @param errorCode the error code, one of the enum ErrorCode
+ */
private void sendMessageDeliveryStatusToContextHub(int contextHubId,
int messageSequenceNumber, byte errorCode) {
if (!Flags.reliableMessageImplementation()) {
@@ -1229,6 +1419,9 @@
public boolean setTestMode(boolean enable) {
super.setTestMode_enforcePermission();
boolean status = mContextHubWrapper.setTestMode(enable);
+ if (status) {
+ mIsTestModeEnabled.set(enable);
+ }
// Query nanoapps to update service state after test mode state change.
for (int contextHubId: mDefaultClientMap.keySet()) {
diff --git a/services/core/java/com/android/server/notification/GroupHelper.java b/services/core/java/com/android/server/notification/GroupHelper.java
index babb6c2..13cc99c 100644
--- a/services/core/java/com/android/server/notification/GroupHelper.java
+++ b/services/core/java/com/android/server/notification/GroupHelper.java
@@ -108,16 +108,25 @@
return (flags & mask) != 0;
}
- public void onNotificationPosted(StatusBarNotification sbn, boolean autogroupSummaryExists) {
+ /**
+ * Called when a notification is newly posted. Checks whether that notification, and all other
+ * active notifications should be grouped or ungrouped atuomatically, and returns whether.
+ * @param sbn The posted notification.
+ * @param autogroupSummaryExists Whether a summary for this notification already exists.
+ * @return Whether the provided notification should be autogrouped synchronously.
+ */
+ public boolean onNotificationPosted(StatusBarNotification sbn, boolean autogroupSummaryExists) {
+ boolean sbnToBeAutogrouped = false;
try {
if (!sbn.isAppGroup()) {
- maybeGroup(sbn, autogroupSummaryExists);
+ sbnToBeAutogrouped = maybeGroup(sbn, autogroupSummaryExists);
} else {
maybeUngroup(sbn, false, sbn.getUserId());
}
} catch (Exception e) {
Slog.e(TAG, "Failure processing new notification", e);
}
+ return sbnToBeAutogrouped;
}
public void onNotificationRemoved(StatusBarNotification sbn) {
@@ -137,20 +146,22 @@
*
* And stores the list of upgrouped notifications & their flags
*/
- private void maybeGroup(StatusBarNotification sbn, boolean autogroupSummaryExists) {
+ private boolean maybeGroup(StatusBarNotification sbn, boolean autogroupSummaryExists) {
int flags = 0;
List<String> notificationsToGroup = new ArrayList<>();
List<NotificationAttributes> childrenAttr = new ArrayList<>();
+ // Indicates whether the provided sbn should be autogrouped by the caller.
+ boolean sbnToBeAutogrouped = false;
synchronized (mUngroupedNotifications) {
- String key = generatePackageKey(sbn.getUserId(), sbn.getPackageName());
+ String packageKey = generatePackageKey(sbn.getUserId(), sbn.getPackageName());
final ArrayMap<String, NotificationAttributes> children =
- mUngroupedNotifications.getOrDefault(key, new ArrayMap<>());
+ mUngroupedNotifications.getOrDefault(packageKey, new ArrayMap<>());
NotificationAttributes attr = new NotificationAttributes(sbn.getNotification().flags,
sbn.getNotification().getSmallIcon(), sbn.getNotification().color,
sbn.getNotification().visibility);
children.put(sbn.getKey(), attr);
- mUngroupedNotifications.put(key, children);
+ mUngroupedNotifications.put(packageKey, children);
if (children.size() >= mAutoGroupAtCount || autogroupSummaryExists) {
flags = getAutogroupSummaryFlags(children);
@@ -187,10 +198,20 @@
mCallback.addAutoGroupSummary(sbn.getUserId(), sbn.getPackageName(), sbn.getKey(),
attr);
}
- for (String key : notificationsToGroup) {
- mCallback.addAutoGroup(key);
+ for (String keyToGroup : notificationsToGroup) {
+ if (android.app.Flags.checkAutogroupBeforePost()) {
+ if (keyToGroup.equals(sbn.getKey())) {
+ // Autogrouping for the provided notification is to be done synchronously.
+ sbnToBeAutogrouped = true;
+ } else {
+ mCallback.addAutoGroup(keyToGroup, /*requestSort=*/true);
+ }
+ } else {
+ mCallback.addAutoGroup(keyToGroup, /*requestSort=*/true);
+ }
}
}
+ return sbnToBeAutogrouped;
}
/**
@@ -406,7 +427,7 @@
}
protected interface Callback {
- void addAutoGroup(String key);
+ void addAutoGroup(String key, boolean requestSort);
void removeAutoGroup(String key);
void addAutoGroupSummary(int userId, String pkg, String triggeringKey,
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index ca6ae63..42ec1c3 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -245,7 +245,6 @@
import android.os.DeviceIdleManager;
import android.os.Environment;
import android.os.Handler;
-import android.os.HandlerExecutor;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.IInterface;
@@ -2038,19 +2037,21 @@
mSnoozeHelper.clearData(userHandle);
}
} else if (action.equals(Intent.ACTION_USER_SWITCHED)) {
- final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, USER_NULL);
- mUserProfiles.updateCache(context);
- if (!mUserProfiles.isProfileUser(userId, context)) {
- // reload per-user settings
- mSettingsObserver.update(null);
- // Refresh managed services
- mConditionProviders.onUserSwitched(userId);
- mListeners.onUserSwitched(userId);
- mZenModeHelper.onUserSwitched(userId);
- mPreferencesHelper.syncChannelsBypassingDnd();
+ if (!Flags.useSsmUserSwitchSignal()) {
+ final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, USER_NULL);
+ mUserProfiles.updateCache(context);
+ if (!mUserProfiles.isProfileUser(userId, context)) {
+ // reload per-user settings
+ mSettingsObserver.update(null);
+ // Refresh managed services
+ mConditionProviders.onUserSwitched(userId);
+ mListeners.onUserSwitched(userId);
+ mZenModeHelper.onUserSwitched(userId);
+ mPreferencesHelper.syncChannelsBypassingDnd();
+ }
+ // assistant is the only thing that cares about managed profiles specifically
+ mAssistants.onUserSwitched(userId);
}
- // assistant is the only thing that cares about managed profiles specifically
- mAssistants.onUserSwitched(userId);
} else if (action.equals(Intent.ACTION_USER_ADDED)) {
final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, USER_NULL);
if (userId != USER_NULL) {
@@ -2570,7 +2571,9 @@
// calling onDestroy()
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_USER_STOPPED);
- filter.addAction(Intent.ACTION_USER_SWITCHED);
+ if (!Flags.useSsmUserSwitchSignal()) {
+ filter.addAction(Intent.ACTION_USER_SWITCHED);
+ }
filter.addAction(Intent.ACTION_USER_ADDED);
filter.addAction(Intent.ACTION_USER_REMOVED);
filter.addAction(Intent.ACTION_USER_UNLOCKED);
@@ -2793,10 +2796,10 @@
return new GroupHelper(getContext(), getContext().getPackageManager(),
mAutoGroupAtCount, new GroupHelper.Callback() {
@Override
- public void addAutoGroup(String key) {
- synchronized (mNotificationLock) {
- addAutogroupKeyLocked(key);
- }
+ public void addAutoGroup(String key, boolean requestSort) {
+ synchronized (mNotificationLock) {
+ addAutogroupKeyLocked(key, requestSort);
+ }
}
@Override
@@ -2966,6 +2969,26 @@
}
@Override
+ public void onUserSwitching(@Nullable TargetUser from, @NonNull TargetUser to) {
+ if (!Flags.useSsmUserSwitchSignal()) {
+ return;
+ }
+ final int userId = to.getUserIdentifier();
+ mUserProfiles.updateCache(getContext());
+ if (!mUserProfiles.isProfileUser(userId, getContext())) {
+ // reload per-user settings
+ mSettingsObserver.update(null);
+ // Refresh managed services
+ mConditionProviders.onUserSwitched(userId);
+ mListeners.onUserSwitched(userId);
+ mZenModeHelper.onUserSwitched(userId);
+ mPreferencesHelper.syncChannelsBypassingDnd();
+ }
+ // assistant is the only thing that cares about managed profiles specifically
+ mAssistants.onUserSwitched(userId);
+ }
+
+ @Override
public void onUserStopping(@NonNull TargetUser user) {
mHandler.post(() -> {
Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "notifHistoryStopUser");
@@ -6538,7 +6561,7 @@
}
@GuardedBy("mNotificationLock")
- void addAutogroupKeyLocked(String key) {
+ void addAutogroupKeyLocked(String key, boolean requestSort) {
NotificationRecord r = mNotificationsByKey.get(key);
if (r == null) {
return;
@@ -6546,7 +6569,9 @@
if (r.getSbn().getOverrideGroupKey() == null) {
addAutoGroupAdjustment(r, GroupHelper.AUTOGROUP_KEY);
EventLogTags.writeNotificationAutogrouped(key);
- mRankingHandler.requestSort();
+ if (!android.app.Flags.checkAutogroupBeforePost() || requestSort) {
+ mRankingHandler.requestSort();
+ }
}
}
@@ -8609,6 +8634,29 @@
notification.flags |= FLAG_NO_CLEAR;
}
+ // Posts the notification if it has a small icon, and potentially autogroup
+ // the new notification.
+ if (android.app.Flags.checkAutogroupBeforePost()) {
+ if (notification.getSmallIcon() != null && !isCritical(r)) {
+ StatusBarNotification oldSbn = (old != null) ? old.getSbn() : null;
+ if (oldSbn == null || !Objects.equals(oldSbn.getGroup(), n.getGroup())
+ || oldSbn.getNotification().flags
+ != n.getNotification().flags) {
+ synchronized (mNotificationLock) {
+ boolean willBeAutogrouped = mGroupHelper.onNotificationPosted(n,
+ hasAutoGroupSummaryLocked(n));
+ if (willBeAutogrouped) {
+ // The newly posted notification will be autogrouped, but
+ // was not autogrouped onPost, to avoid an unnecessary sort.
+ // We add the autogroup key to the notification without a
+ // sort here, and it'll be sorted below with extractSignals.
+ addAutogroupKeyLocked(key, /*requestSort=*/false);
+ }
+ }
+ }
+ }
+ }
+
mRankingHelper.extractSignals(r);
mRankingHelper.sort(mNotificationList);
final int position = mRankingHelper.indexOf(mNotificationList, r);
@@ -8629,17 +8677,20 @@
notifyListenersPostedAndLogLocked(r, old, mTracker, maybeReport);
posted = true;
- StatusBarNotification oldSbn = (old != null) ? old.getSbn() : null;
- if (oldSbn == null
- || !Objects.equals(oldSbn.getGroup(), n.getGroup())
- || oldSbn.getNotification().flags != n.getNotification().flags) {
- if (!isCritical(r)) {
- mHandler.post(() -> {
- synchronized (mNotificationLock) {
- mGroupHelper.onNotificationPosted(
- n, hasAutoGroupSummaryLocked(n));
- }
- });
+ if (!android.app.Flags.checkAutogroupBeforePost()) {
+ StatusBarNotification oldSbn = (old != null) ? old.getSbn() : null;
+ if (oldSbn == null
+ || !Objects.equals(oldSbn.getGroup(), n.getGroup())
+ || oldSbn.getNotification().flags
+ != n.getNotification().flags) {
+ if (!isCritical(r)) {
+ mHandler.post(() -> {
+ synchronized (mNotificationLock) {
+ mGroupHelper.onNotificationPosted(
+ n, hasAutoGroupSummaryLocked(n));
+ }
+ });
+ }
}
}
} else {
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 143bc5c..b589f49 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -486,6 +486,7 @@
}
}
+ @GuardedBy("mConfigLock")
private ZenRule maybeRestoreRemovedRule(ZenModeConfig config, ZenRule ruleToAdd,
AutomaticZenRule azrToAdd, @ConfigChangeOrigin int origin) {
if (!Flags.modesApi()) {
@@ -1112,6 +1113,7 @@
* <p>The rule's {@link ZenRule#condition} is cleared (meaning that an active rule will be
* deactivated) unless the update has origin == {@link ZenModeConfig#UPDATE_ORIGIN_USER}.
*/
+ @GuardedBy("mConfigLock")
private boolean populateZenRule(String pkg, AutomaticZenRule azr, ZenRule rule,
@ConfigChangeOrigin int origin, boolean isNew) {
if (Flags.modesApi()) {
@@ -1261,12 +1263,14 @@
*
* <p>Returns {@code true} if the policy of the rule was modified.
*/
+ @GuardedBy("mConfigLock")
private boolean updatePolicy(ZenRule zenRule, @Nullable ZenPolicy newPolicy,
boolean updateBitmask, boolean isNew) {
if (newPolicy == null) {
if (isNew) {
// Newly created rule with no provided policy; fill in with the default.
- zenRule.zenPolicy = mDefaultConfig.toZenPolicy();
+ zenRule.zenPolicy =
+ Flags.modesUi() ? mDefaultConfig.toZenPolicy() : mConfig.toZenPolicy();
return true;
}
// Otherwise, a null policy means no policy changes, so we can stop here.
@@ -1275,8 +1279,9 @@
// If oldPolicy is null, we compare against the default policy when determining which
// fields in the bitmask should be marked as updated.
- ZenPolicy oldPolicy =
- zenRule.zenPolicy != null ? zenRule.zenPolicy : mDefaultConfig.toZenPolicy();
+ ZenPolicy oldPolicy = zenRule.zenPolicy != null
+ ? zenRule.zenPolicy
+ : (Flags.modesUi() ? mDefaultConfig.toZenPolicy() : mConfig.toZenPolicy());
// If this is updating a rule rather than creating a new one, keep any fields from the
// old policy if they are unspecified in the new policy. For newly created rules, oldPolicy
@@ -2033,7 +2038,8 @@
// rule's policy fields should be set upon creation, this is a fallback to
// catch any that may have fallen through the cracks.
Log.wtf(TAG, "active automatic rule found with no specified policy: " + rule);
- policy.apply(mDefaultConfig.toZenPolicy());
+ policy.apply(
+ Flags.modesUi() ? mDefaultConfig.toZenPolicy() : mConfig.toZenPolicy());
}
} else {
// active rule with no specified policy inherits the global config settings
diff --git a/services/core/java/com/android/server/notification/flags.aconfig b/services/core/java/com/android/server/notification/flags.aconfig
index af3db6c..9dcca49 100644
--- a/services/core/java/com/android/server/notification/flags.aconfig
+++ b/services/core/java/com/android/server/notification/flags.aconfig
@@ -128,3 +128,10 @@
description: "Adds an IPCDataCache for notification channel/group lookups"
bug: "331677193"
}
+
+flag {
+ name: "use_ssm_user_switch_signal"
+ namespace: "systemui"
+ description: "This flag controls which signal is used to handle a user switch system event"
+ bug: "337077643"
+}
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index 6c93fe7..56e4590 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -89,6 +89,7 @@
import com.android.server.SystemConfig;
import com.android.server.SystemService;
import com.android.server.pm.KnownPackages;
+import com.android.server.pm.UserManagerInternal;
import com.android.server.pm.UserManagerService;
import com.android.server.pm.pkg.PackageState;
@@ -289,6 +290,9 @@
getContext().registerReceiverAsUser(new UserReceiver(), UserHandle.ALL,
userFilter, null, null);
+ UserManagerInternal umi = LocalServices.getService(UserManagerInternal.class);
+ umi.addUserLifecycleListener(new UserLifecycleListener());
+
restoreSettings();
// Wipe all shell overlays on boot, to recover from a potentially broken device
@@ -339,6 +343,7 @@
if (newUserId == mPrevStartedUserId) {
return;
}
+ Slog.i(TAG, "Updating overlays for starting user " + newUserId);
try {
traceBegin(TRACE_TAG_RRO, "OMS#onStartUser " + newUserId);
// ensure overlays in the settings are up-to-date, and propagate
@@ -515,14 +520,46 @@
}
}
+ /**
+ * Indicates that the given user is of great importance so that when it is created, we quickly
+ * update its overlays by using a Listener mechanism rather than a Broadcast mechanism. This
+ * is especially important for {@link UserManager#isHeadlessSystemUserMode() HSUM}'s MainUser,
+ * which is created and switched-to immediately on first boot.
+ */
+ private static boolean isHighPriorityUserCreation(UserInfo user) {
+ // TODO: Consider extending this to all created users (guarded behind a flag in that case).
+ return user != null && user.isMain();
+ }
+
+ private final class UserLifecycleListener implements UserManagerInternal.UserLifecycleListener {
+ @Override
+ public void onUserCreated(UserInfo user, Object token) {
+ if (isHighPriorityUserCreation(user)) {
+ final int userId = user.id;
+ try {
+ Slog.i(TAG, "Updating overlays for onUserCreated " + userId);
+ traceBegin(TRACE_TAG_RRO, "OMS#onUserCreated " + userId);
+ synchronized (mLock) {
+ updatePackageManagerLocked(mImpl.updateOverlaysForUser(userId));
+ }
+ } finally {
+ traceEnd(TRACE_TAG_RRO);
+ }
+ }
+ }
+ }
+
private final class UserReceiver extends BroadcastReceiver {
@Override
public void onReceive(@NonNull final Context context, @NonNull final Intent intent) {
final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
switch (intent.getAction()) {
case ACTION_USER_ADDED:
- if (userId != UserHandle.USER_NULL) {
+ UserManagerInternal umi = LocalServices.getService(UserManagerInternal.class);
+ UserInfo userInfo = umi.getUserInfo(userId);
+ if (userId != UserHandle.USER_NULL && !isHighPriorityUserCreation(userInfo)) {
try {
+ Slog.i(TAG, "Updating overlays for added user " + userId);
traceBegin(TRACE_TAG_RRO, "OMS ACTION_USER_ADDED");
synchronized (mLock) {
updatePackageManagerLocked(mImpl.updateOverlaysForUser(userId));
diff --git a/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java b/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
index 8a85328..71a7d0d 100644
--- a/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
+++ b/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
@@ -46,6 +46,7 @@
import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.LocalLog;
+import android.util.MutableBoolean;
import android.util.Pair;
import android.util.Slog;
import android.util.Xml;
@@ -104,6 +105,7 @@
private final TelephonyManager mTelephonyManager;
private final ArraySet<String> mBugreportAllowlistedPackages;
private final BugreportFileManager mBugreportFileManager;
+ private static final FeatureFlags sFeatureFlags = new FeatureFlagsImpl();
@GuardedBy("mLock")
@@ -429,9 +431,51 @@
ensureUserCanTakeBugReport(bugreportMode);
Slogf.i(TAG, "Starting bugreport for %s / %d", callingPackage, callingUid);
- synchronized (mLock) {
- startBugreportLocked(callingUid, callingPackage, bugreportFd, screenshotFd,
- bugreportMode, bugreportFlags, listener, isScreenshotRequested);
+ final MutableBoolean handoffLock = new MutableBoolean(false);
+ if (sFeatureFlags.asyncStartBugreport()) {
+ synchronized (handoffLock) {
+ new Thread(()-> {
+ try {
+ synchronized (mLock) {
+ synchronized (handoffLock) {
+ handoffLock.value = true;
+ handoffLock.notifyAll();
+ }
+ startBugreportLocked(
+ callingUid,
+ callingPackage,
+ bugreportFd,
+ screenshotFd,
+ bugreportMode,
+ bugreportFlags,
+ listener,
+ isScreenshotRequested);
+ }
+ } catch (Exception e) {
+ Slog.e(TAG, "Cannot start a new bugreport due to an unknown error", e);
+ reportError(listener, IDumpstateListener.BUGREPORT_ERROR_RUNTIME_ERROR);
+ }
+ }, "BugreportManagerServiceThread").start();
+ try {
+ while (!handoffLock.value) { // handle the rare case of a spurious wakeup
+ handoffLock.wait(DEFAULT_BUGREPORT_SERVICE_TIMEOUT_MILLIS);
+ }
+ } catch (InterruptedException e) {
+ Slog.e(TAG, "Unexpectedly interrupted waiting for startBugreportLocked", e);
+ }
+ }
+ } else {
+ synchronized (mLock) {
+ startBugreportLocked(
+ callingUid,
+ callingPackage,
+ bugreportFd,
+ screenshotFd,
+ bugreportMode,
+ bugreportFlags,
+ listener,
+ isScreenshotRequested);
+ }
}
}
diff --git a/services/core/java/com/android/server/os/core_os_flags.aconfig b/services/core/java/com/android/server/os/core_os_flags.aconfig
index ae33df8..efdc9b8 100644
--- a/services/core/java/com/android/server/os/core_os_flags.aconfig
+++ b/services/core/java/com/android/server/os/core_os_flags.aconfig
@@ -7,3 +7,13 @@
description: "Use proto tombstones as source of truth for adding to dropbox"
bug: "323857385"
}
+
+flag {
+ name: "async_start_bugreport"
+ namespace: "crumpet"
+ description: "Don't block callers on the start of dumpsys service"
+ bug: "180123623"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/services/core/java/com/android/server/pdb/PersistentDataBlockService.java b/services/core/java/com/android/server/pdb/PersistentDataBlockService.java
index 2c14532..c5e2bb8 100644
--- a/services/core/java/com/android/server/pdb/PersistentDataBlockService.java
+++ b/services/core/java/com/android/server/pdb/PersistentDataBlockService.java
@@ -291,9 +291,15 @@
private void setOldSettingForBackworkCompatibility(boolean isActive) {
// Set the SECURE_FRP_MODE flag, for backward compatibility with clients who use it.
- // They should switch to calling #isFrpActive().
- Settings.Global.putInt(mContext.getContentResolver(),
- Settings.Global.SECURE_FRP_MODE, isActive ? 1 : 0);
+ // They should switch to calling #isFrpActive(). Clear calling ID since this can happen
+ // during an app call.
+ final long callingId = Binder.clearCallingIdentity();
+ try {
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.SECURE_FRP_MODE, isActive ? 1 : 0);
+ } finally {
+ Binder.restoreCallingIdentity(callingId);
+ }
}
private void setOemUnlockEnabledProperty(boolean oemUnlockEnabled) {
diff --git a/services/core/java/com/android/server/pm/DefaultCrossProfileIntentFiltersUtils.java b/services/core/java/com/android/server/pm/DefaultCrossProfileIntentFiltersUtils.java
index 306f77d..5ac883c 100644
--- a/services/core/java/com/android/server/pm/DefaultCrossProfileIntentFiltersUtils.java
+++ b/services/core/java/com/android/server/pm/DefaultCrossProfileIntentFiltersUtils.java
@@ -688,6 +688,29 @@
);
}
+ /** Call intent should be handled by the main user. */
+ private static final DefaultCrossProfileIntentFilter CALL_PRIVATE_PROFILE =
+ new DefaultCrossProfileIntentFilter.Builder(
+ DefaultCrossProfileIntentFilter.Direction.TO_PARENT,
+ SKIP_CURRENT_PROFILE,
+ /* letsPersonalDataIntoProfile= */ false)
+ .addAction(Intent.ACTION_CALL)
+ .addCategory(Intent.CATEGORY_DEFAULT)
+ .addDataScheme("tel")
+ .addDataScheme("sip")
+ .addDataScheme("voicemail")
+ .build();
+
+ /** Pressing the call button should be handled by the main user. */
+ private static final DefaultCrossProfileIntentFilter CALL_BUTTON_PRIVATE_PROFILE =
+ new DefaultCrossProfileIntentFilter.Builder(
+ DefaultCrossProfileIntentFilter.Direction.TO_PARENT,
+ ONLY_IF_NO_MATCH_FOUND,
+ /* letsPersonalDataIntoProfile= */ false)
+ .addAction(Intent.ACTION_CALL_BUTTON)
+ .addCategory(Intent.CATEGORY_DEFAULT)
+ .build();
+
/** Dial intent with mime type can be handled by either private profile or its parent user. */
private static final DefaultCrossProfileIntentFilter DIAL_MIME_PRIVATE_PROFILE =
new DefaultCrossProfileIntentFilter.Builder(
@@ -734,11 +757,11 @@
.addCategory(Intent.CATEGORY_BROWSABLE)
.build();
- /** SMS and MMS can be handled by the private profile or by the parent user. */
+ /** SMS and MMS are always handled in the main user. */
private static final DefaultCrossProfileIntentFilter SMS_MMS_PRIVATE_PROFILE =
new DefaultCrossProfileIntentFilter.Builder(
DefaultCrossProfileIntentFilter.Direction.TO_PARENT,
- ONLY_IF_NO_MATCH_FOUND,
+ SKIP_CURRENT_PROFILE,
/* letsPersonalDataIntoProfile= */ false)
.addAction(Intent.ACTION_VIEW)
.addAction(Intent.ACTION_SENDTO)
@@ -755,6 +778,10 @@
DIAL_MIME_PRIVATE_PROFILE,
DIAL_DATA_PRIVATE_PROFILE,
DIAL_RAW_PRIVATE_PROFILE,
+ CALL_PRIVATE_PROFILE,
+ CALL_BUTTON_PRIVATE_PROFILE,
+ EMERGENCY_CALL_DATA,
+ EMERGENCY_CALL_MIME,
SMS_MMS_PRIVATE_PROFILE
);
}
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index 326d414d..19a0ba7 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -2950,7 +2950,6 @@
info.mRemovedUsers = firstUserIds;
info.mBroadcastUsers = firstUserIds;
info.mUid = request.getAppId();
- info.mIsAppIdRemoved = true;
info.mRemovedPackageVersionCode = request.getPkg().getLongVersionCode();
info.mRemovedForAllUsers = true;
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index fa54f6e..b369f03 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -1667,15 +1667,6 @@
if (appMetadataFile.exists()) {
return true;
}
- if (isSystem) {
- try {
- makeDirRecursive(new File(appMetadataFilePath).getParentFile(), 0700);
- } catch (Exception e) {
- Slog.e(TAG, "Failed to create app metadata dir for package "
- + pkg.getPackageName() + ": " + e.getMessage());
- return false;
- }
- }
Map<String, Property> properties = pkg.getProperties();
if (!properties.containsKey(PROPERTY_ANDROID_SAFETY_LABEL_PATH)) {
return false;
@@ -1684,6 +1675,15 @@
if (!fileInAPkPathProperty.isString()) {
return false;
}
+ if (isSystem && !appMetadataFile.getParentFile().exists()) {
+ try {
+ makeDirRecursive(appMetadataFile.getParentFile(), 0700);
+ } catch (Exception e) {
+ Slog.e(TAG, "Failed to create app metadata dir for package "
+ + pkg.getPackageName() + ": " + e.getMessage());
+ return false;
+ }
+ }
String fileInApkPath = fileInAPkPathProperty.getString();
List<AndroidPackageSplit> splits = pkg.getSplits();
for (int i = 0; i < splits.size(); i++) {
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 3f5ec06..9edf3b1 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -50,7 +50,6 @@
import android.content.pm.IPackageManager;
import android.content.pm.IShortcutService;
import android.content.pm.LauncherApps;
-import android.content.pm.LauncherApps.ShortcutChangeCallback;
import android.content.pm.LauncherApps.ShortcutQuery;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
@@ -152,7 +151,6 @@
import java.util.Collections;
import java.util.List;
import java.util.Objects;
-import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Consumer;
@@ -174,7 +172,7 @@
static final boolean DEBUG = false; // STOPSHIP if true
static final boolean DEBUG_LOAD = false; // STOPSHIP if true
static final boolean DEBUG_PROCSTATE = false; // STOPSHIP if true
- static final boolean DEBUG_REBOOT = false; // STOPSHIP if true
+ static final boolean DEBUG_REBOOT = true;
@VisibleForTesting
static final long DEFAULT_RESET_INTERVAL_SEC = 24 * 60 * 60; // 1 day
@@ -322,11 +320,12 @@
private final Handler mHandler;
- private final CopyOnWriteArrayList<ShortcutChangeListener> mListeners =
- new CopyOnWriteArrayList<>();
+ @GuardedBy("mServiceLock")
+ private final ArrayList<ShortcutChangeListener> mListeners = new ArrayList<>(1);
- private final CopyOnWriteArrayList<ShortcutChangeCallback> mShortcutChangeCallbacks =
- new CopyOnWriteArrayList<>();
+ @GuardedBy("mServiceLock")
+ private final ArrayList<LauncherApps.ShortcutChangeCallback> mShortcutChangeCallbacks =
+ new ArrayList<>(1);
private final AtomicLong mRawLastResetTime = new AtomicLong(0);
@@ -1842,11 +1841,18 @@
@UserIdInt final int userId) {
return () -> {
try {
- if (!isUserUnlockedL(userId)) {
- return;
+ final ArrayList<ShortcutChangeListener> copy;
+ synchronized (mServiceLock) {
+ if (!isUserUnlockedL(userId)) {
+ return;
+ }
+
+ copy = new ArrayList<>(mListeners);
}
// Note onShortcutChanged() needs to be called with the system service permissions.
- mListeners.forEach(listener -> listener.onShortcutChanged(packageName, userId));
+ for (int i = copy.size() - 1; i >= 0; i--) {
+ copy.get(i).onShortcutChanged(packageName, userId);
+ }
} catch (Exception ignore) {
}
};
@@ -1861,17 +1867,22 @@
final UserHandle user = UserHandle.of(userId);
injectPostToHandler(() -> {
try {
- if (!isUserUnlockedL(userId)) {
- return;
+ final ArrayList<LauncherApps.ShortcutChangeCallback> copy;
+ synchronized (mServiceLock) {
+ if (!isUserUnlockedL(userId)) {
+ return;
+ }
+
+ copy = new ArrayList<>(mShortcutChangeCallbacks);
}
- mShortcutChangeCallbacks.forEach(callback -> {
+ for (int i = copy.size() - 1; i >= 0; i--) {
if (!CollectionUtils.isEmpty(changedList)) {
- callback.onShortcutsAddedOrUpdated(packageName, changedList, user);
+ copy.get(i).onShortcutsAddedOrUpdated(packageName, changedList, user);
}
if (!CollectionUtils.isEmpty(removedList)) {
- callback.onShortcutsRemoved(packageName, removedList, user);
+ copy.get(i).onShortcutsRemoved(packageName, removedList, user);
}
- });
+ }
} catch (Exception ignore) {
}
});
@@ -3414,13 +3425,17 @@
@Override
public void addListener(@NonNull ShortcutChangeListener listener) {
- mListeners.add(Objects.requireNonNull(listener));
+ synchronized (mServiceLock) {
+ mListeners.add(Objects.requireNonNull(listener));
+ }
}
@Override
public void addShortcutChangeCallback(
@NonNull LauncherApps.ShortcutChangeCallback callback) {
- mShortcutChangeCallbacks.add(Objects.requireNonNull(callback));
+ synchronized (mServiceLock) {
+ mShortcutChangeCallbacks.add(Objects.requireNonNull(callback));
+ }
}
@Override
@@ -3783,24 +3798,36 @@
final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
final boolean archival = intent.getBooleanExtra(Intent.EXTRA_ARCHIVAL, false);
+ Slog.d(TAG, "received package broadcast intent: " + intent);
switch (action) {
case Intent.ACTION_PACKAGE_ADDED:
if (replacing) {
+ Slog.d(TAG, "replacing package: " + packageName + " userId" + userId);
handlePackageUpdateFinished(packageName, userId);
} else {
+ Slog.d(TAG, "adding package: " + packageName + " userId" + userId);
handlePackageAdded(packageName, userId);
}
break;
case Intent.ACTION_PACKAGE_REMOVED:
if (!replacing || (replacing && archival)) {
+ if (!replacing) {
+ Slog.d(TAG, "removing package: "
+ + packageName + " userId" + userId);
+ } else if (archival) {
+ Slog.d(TAG, "archiving package: "
+ + packageName + " userId" + userId);
+ }
handlePackageRemoved(packageName, userId);
}
break;
case Intent.ACTION_PACKAGE_CHANGED:
+ Slog.d(TAG, "changing package: " + packageName + " userId" + userId);
handlePackageChanged(packageName, userId);
-
break;
case Intent.ACTION_PACKAGE_DATA_CLEARED:
+ Slog.d(TAG, "clearing data for package: "
+ + packageName + " userId" + userId);
handlePackageDataCleared(packageName, userId);
break;
}
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index ba845da..f6487ce 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -7166,6 +7166,7 @@
synchronized (mUsersLock) {
pw.println(" Boot user: " + mBootUser);
}
+ pw.println("Can add private profile: "+ canAddPrivateProfile(currentUserId));
pw.println();
pw.println("Number of listeners for");
diff --git a/services/core/java/com/android/server/power/batterysaver/Android.bp b/services/core/java/com/android/server/power/batterysaver/Android.bp
new file mode 100644
index 0000000..0b04345
--- /dev/null
+++ b/services/core/java/com/android/server/power/batterysaver/Android.bp
@@ -0,0 +1,14 @@
+aconfig_declarations {
+ name: "battery_saver_flag",
+ package: "com.android.server.power.batterysaver",
+ container: "system",
+ srcs: [
+ "*.aconfig",
+ ],
+}
+
+java_aconfig_library {
+ name: "battery_saver_flag_lib",
+ aconfig_declarations: "battery_saver_flag",
+ sdk_version: "system_current",
+}
diff --git a/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java b/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java
index c8cb92b..9a4c60d 100644
--- a/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java
+++ b/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java
@@ -29,6 +29,7 @@
import android.content.res.Resources;
import android.database.ContentObserver;
import android.os.BatterySaverPolicyConfig;
+import android.os.Bundle;
import android.os.Handler;
import android.os.PowerManager;
import android.os.SystemClock;
@@ -97,6 +98,9 @@
private static final String TAG = "BatterySaverStateMachine";
private static final String DYNAMIC_MODE_NOTIF_CHANNEL_ID = "dynamic_mode_notification";
private static final String BATTERY_SAVER_NOTIF_CHANNEL_ID = "battery_saver_channel";
+ private static final String EXTRA_FRAGMENT_ARG_KEY = ":settings:fragment_args_key";
+ private static final String EXTRA_SHOW_FRAGMENT_TITLE = ":settings:show_fragment_args";
+ private static final String PREFERENCE_KEY_BATTERY_SAVER_SCHEDULER = "battery_saver_schedule";
private static final int DYNAMIC_MODE_NOTIFICATION_ID = 1992;
private static final int STICKY_AUTO_DISABLED_NOTIFICATION_ID = 1993;
private final Object mLock;
@@ -831,7 +835,11 @@
// Handle triggering the notification to show/hide when appropriate
if (intReason == BatterySaverController.REASON_DYNAMIC_POWER_SAVINGS_AUTOMATIC_ON
|| intReason == BatterySaverController.REASON_PERCENTAGE_AUTOMATIC_ON) {
- triggerDynamicModeNotification();
+ if (Flags.updateAutoTurnOnNotificationStringAndAction()) {
+ triggerDynamicModeNotificationV2();
+ } else {
+ triggerDynamicModeNotification();
+ }
} else if (!enable) {
hideDynamicModeNotification();
}
@@ -862,6 +870,31 @@
}
@VisibleForTesting
+ void triggerDynamicModeNotificationV2() {
+ // The current lock is the PowerManager lock, which sits very low in the service lock
+ // hierarchy. We shouldn't call out to NotificationManager with the PowerManager lock.
+ runOnBgThread(() -> {
+ NotificationManager manager = mContext.getSystemService(NotificationManager.class);
+ ensureNotificationChannelExists(manager, DYNAMIC_MODE_NOTIF_CHANNEL_ID,
+ R.string.dynamic_mode_notification_channel_name);
+
+ // The bundle is used for highlighting a settings item when launching the settings page.
+ final var highlightBundle = new Bundle(1 /* capacity */);
+ highlightBundle.putString(
+ EXTRA_FRAGMENT_ARG_KEY, PREFERENCE_KEY_BATTERY_SAVER_SCHEDULER);
+
+ manager.notifyAsUser(TAG, DYNAMIC_MODE_NOTIFICATION_ID,
+ buildNotificationV2(DYNAMIC_MODE_NOTIF_CHANNEL_ID,
+ R.string.dynamic_mode_notification_title_v2,
+ R.string.dynamic_mode_notification_summary_v2,
+ Settings.ACTION_BATTERY_SAVER_SETTINGS,
+ 0L /* timeoutMs */,
+ highlightBundle),
+ UserHandle.ALL);
+ });
+ }
+
+ @VisibleForTesting
void triggerStickyDisabledNotification() {
if (!mBatterySaverTurnedOffNotificationEnabled) {
return;
@@ -915,6 +948,32 @@
.build();
}
+ private Notification buildNotificationV2(@NonNull String channelId, @StringRes int titleId,
+ @StringRes int summaryId, @NonNull String intentAction, long timeoutMs,
+ @NonNull Bundle highlightBundle) {
+ Resources res = mContext.getResources();
+ Intent intent = new Intent(intentAction)
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK)
+ .putExtra(EXTRA_SHOW_FRAGMENT_TITLE, highlightBundle);
+
+ PendingIntent batterySaverIntent = PendingIntent.getActivity(
+ mContext, 0 /* requestCode */, intent,
+ PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
+ final String title = res.getString(titleId);
+ final String summary = res.getString(summaryId);
+
+ return new Notification.Builder(mContext, channelId)
+ .setSmallIcon(R.drawable.ic_battery)
+ .setContentTitle(title)
+ .setContentText(summary)
+ .setContentIntent(batterySaverIntent)
+ .setStyle(new Notification.BigTextStyle().bigText(summary))
+ .setOnlyAlertOnce(true)
+ .setAutoCancel(true)
+ .setTimeoutAfter(timeoutMs)
+ .build();
+ }
+
private void hideDynamicModeNotification() {
hideNotification(DYNAMIC_MODE_NOTIFICATION_ID);
}
diff --git a/services/core/java/com/android/server/power/batterysaver/flags.aconfig b/services/core/java/com/android/server/power/batterysaver/flags.aconfig
new file mode 100644
index 0000000..1dea523
--- /dev/null
+++ b/services/core/java/com/android/server/power/batterysaver/flags.aconfig
@@ -0,0 +1,12 @@
+package: "com.android.server.power.batterysaver"
+container: "system"
+
+flag {
+ name: "update_auto_turn_on_notification_string_and_action"
+ namespace: "backstage_power"
+ description: "Improve the string and hightligh settings item for battery saver auto-turn-on notification"
+ bug: "336960905"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/services/core/java/com/android/server/power/hint/HintManagerService.java b/services/core/java/com/android/server/power/hint/HintManagerService.java
index 4ddd546..267ddd0 100644
--- a/services/core/java/com/android/server/power/hint/HintManagerService.java
+++ b/services/core/java/com/android/server/power/hint/HintManagerService.java
@@ -16,6 +16,8 @@
package com.android.server.power.hint;
+import static android.os.Flags.adpfUseFmqChannel;
+
import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR;
import static com.android.server.power.hint.Flags.powerhintThreadCleanup;
@@ -26,6 +28,8 @@
import android.app.StatsManager;
import android.app.UidObserver;
import android.content.Context;
+import android.hardware.power.ChannelConfig;
+import android.hardware.power.IPower;
import android.hardware.power.SessionConfig;
import android.hardware.power.SessionTag;
import android.hardware.power.WorkDuration;
@@ -39,6 +43,7 @@
import android.os.PerformanceHintManager;
import android.os.Process;
import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.SystemProperties;
import android.text.TextUtils;
import android.util.ArrayMap;
@@ -69,6 +74,7 @@
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Set;
+import java.util.TreeMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -91,9 +97,21 @@
@GuardedBy("mLock")
private final ArrayMap<Integer, ArrayMap<IBinder, ArraySet<AppHintSession>>> mActiveSessions;
+ // Multi-level map storing all the channel binder token death listeners.
+ // First level is keyed by the UID of the client process owning the channel.
+ // Second level is the tgid of the process, which will often just be size one.
+ // Each channel is unique per (tgid, uid) pair, so this map associates each pair with an
+ // object that listens for the death notification of the binder token that was provided by
+ // that client when it created the channel, so we can detect when the client process dies.
+ @GuardedBy("mChannelMapLock")
+ private ArrayMap<Integer, TreeMap<Integer, ChannelItem>> mChannelMap;
+
/** Lock to protect mActiveSessions and the UidObserver. */
private final Object mLock = new Object();
+ /** Lock to protect mChannelMap. */
+ private final Object mChannelMapLock = new Object();
+
@GuardedBy("mNonIsolatedTidsLock")
private final Map<Integer, Set<Long>> mNonIsolatedTids;
@@ -110,6 +128,9 @@
private AtomicBoolean mConfigCreationSupport = new AtomicBoolean(true);
+ private final IPower mPowerHal;
+ private int mPowerHalVersion;
+
private static final String PROPERTY_SF_ENABLE_CPU_HINT = "debug.sf.enable_adpf_cpu_hint";
private static final String PROPERTY_HWUI_ENABLE_HINT_MANAGER = "debug.hwui.use_hint_manager";
@@ -131,12 +152,22 @@
mNonIsolatedTids = null;
}
mActiveSessions = new ArrayMap<>();
+ mChannelMap = new ArrayMap<>();
mNativeWrapper = injector.createNativeWrapper();
mNativeWrapper.halInit();
mHintSessionPreferredRate = mNativeWrapper.halGetHintSessionPreferredRate();
mUidObserver = new MyUidObserver();
mAmInternal = Objects.requireNonNull(
LocalServices.getService(ActivityManagerInternal.class));
+ mPowerHal = injector.createIPower();
+ mPowerHalVersion = 0;
+ if (mPowerHal != null) {
+ try {
+ mPowerHalVersion = mPowerHal.getInterfaceVersion();
+ } catch (RemoteException e) {
+ throw new IllegalStateException("Could not contact PowerHAL!", e);
+ }
+ }
}
private ServiceThread createCleanUpThread() {
@@ -151,6 +182,10 @@
NativeWrapper createNativeWrapper() {
return new NativeWrapper();
}
+ IPower createIPower() {
+ return IPower.Stub.asInterface(
+ ServiceManager.waitForDeclaredService(IPower.DESCRIPTOR + "/default"));
+ }
}
private boolean isHalSupported() {
@@ -344,6 +379,16 @@
}
}
}
+ synchronized (mChannelMapLock) {
+ // Clean up the uid's session channels
+ final TreeMap<Integer, ChannelItem> uidMap = mChannelMap.get(uid);
+ if (uidMap != null) {
+ for (Map.Entry<Integer, ChannelItem> entry : uidMap.entrySet()) {
+ entry.getValue().closeChannel();
+ }
+ mChannelMap.remove(uid);
+ }
+ }
});
}
@@ -383,6 +428,113 @@
}
}
+ /**
+ * Creates a channel item in the channel map if one does not exist, then returns
+ * the entry in the channel map.
+ */
+ public ChannelItem getOrCreateMappedChannelItem(int tgid, int uid, IBinder token) {
+ synchronized (mChannelMapLock) {
+ if (!mChannelMap.containsKey(uid)) {
+ mChannelMap.put(uid, new TreeMap<Integer, ChannelItem>());
+ }
+ TreeMap<Integer, ChannelItem> map = mChannelMap.get(uid);
+ if (!map.containsKey(tgid)) {
+ ChannelItem item = new ChannelItem(tgid, uid, token);
+ item.openChannel();
+ map.put(tgid, item);
+ }
+ return map.get(tgid);
+ }
+ }
+
+ /**
+ * This removes an entry in the binder token callback map when a channel is closed,
+ * and unregisters its callbacks.
+ */
+ public void removeChannelItem(Integer tgid, Integer uid) {
+ synchronized (mChannelMapLock) {
+ TreeMap<Integer, ChannelItem> map = mChannelMap.get(uid);
+ if (map != null) {
+ ChannelItem item = map.get(tgid);
+ if (item != null) {
+ item.closeChannel();
+ map.remove(tgid);
+ }
+ if (map.isEmpty()) {
+ mChannelMap.remove(uid);
+ }
+ }
+ }
+ }
+
+ /**
+ * Manages the lifecycle of a single channel. This includes caching the channel descriptor,
+ * receiving binder token death notifications, and handling cleanup on uid termination. There
+ * can only be one ChannelItem per (tgid, uid) pair in mChannelMap, and channel creation happens
+ * when a ChannelItem enters the map, while destruction happens when it leaves the map.
+ */
+ private class ChannelItem implements IBinder.DeathRecipient {
+ @Override
+ public void binderDied() {
+ removeChannelItem(mTgid, mUid);
+ }
+
+ ChannelItem(int tgid, int uid, IBinder token) {
+ this.mTgid = tgid;
+ this.mUid = uid;
+ this.mToken = token;
+ this.mLinked = false;
+ this.mConfig = null;
+ }
+
+ public void closeChannel() {
+ if (mLinked) {
+ mToken.unlinkToDeath(this, 0);
+ mLinked = false;
+ }
+ if (mConfig != null) {
+ try {
+ mPowerHal.closeSessionChannel(mTgid, mUid);
+ } catch (RemoteException e) {
+ throw new IllegalStateException("Failed to close session channel!", e);
+ }
+ mConfig = null;
+ }
+ }
+
+ public void openChannel() {
+ if (!mLinked) {
+ try {
+ mToken.linkToDeath(this, 0);
+ } catch (RemoteException e) {
+ throw new IllegalStateException("Client already dead", e);
+ }
+ mLinked = true;
+ }
+ if (mConfig == null) {
+ try {
+ // This method uses PowerHAL directly through the SDK,
+ // to avoid needing to pass the ChannelConfig through JNI.
+ mConfig = mPowerHal.getSessionChannel(mTgid, mUid);
+ } catch (RemoteException e) {
+ removeChannelItem(mTgid, mUid);
+ throw new IllegalStateException("Failed to create session channel!", e);
+ }
+ }
+ }
+
+ ChannelConfig getConfig() {
+ return mConfig;
+ }
+
+ // To avoid accidental double-linking / unlinking
+ boolean mLinked;
+ final int mTgid;
+ final int mUid;
+ final IBinder mToken;
+ ChannelConfig mConfig;
+ }
+
final class CleanUpHandler extends Handler {
// status of processed tid used for caching
private static final int TID_NOT_CHECKED = 0;
@@ -570,6 +722,18 @@
return mService;
}
+ @VisibleForTesting
+ Boolean hasChannel(int tgid, int uid) {
+ synchronized (mChannelMapLock) {
+ TreeMap<Integer, ChannelItem> uidMap = mChannelMap.get(uid);
+ if (uidMap != null) {
+ ChannelItem item = uidMap.get(tgid);
+ return item != null;
+ }
+ return false;
+ }
+ }
+
// returns the first invalid tid or null if not found
private Integer checkTidValid(int uid, int tgid, int [] tids, IntArray nonIsolated) {
// Make sure all tids belongs to the same UID (including isolated UID),
@@ -710,6 +874,28 @@
}
@Override
+ public ChannelConfig getSessionChannel(IBinder token) {
+ if (mPowerHalVersion < 5 || !adpfUseFmqChannel()) {
+ return null;
+ }
+ java.util.Objects.requireNonNull(token);
+ final int callingTgid = Process.getThreadGroupLeader(Binder.getCallingPid());
+ final int callingUid = Binder.getCallingUid();
+ ChannelItem item = getOrCreateMappedChannelItem(callingTgid, callingUid, token);
+ return item.getConfig();
+ };
+
+ @Override
+ public void closeSessionChannel() {
+ if (mPowerHalVersion < 5 || !adpfUseFmqChannel()) {
+ return;
+ }
+ final int callingTgid = Process.getThreadGroupLeader(Binder.getCallingPid());
+ final int callingUid = Binder.getCallingUid();
+ removeChannelItem(callingTgid, callingUid);
+ };
+
+ @Override
public long getHintSessionPreferredRate() {
return mHintSessionPreferredRate;
}
diff --git a/services/core/java/com/android/server/vcn/routeselection/IpSecPacketLossDetector.java b/services/core/java/com/android/server/vcn/routeselection/IpSecPacketLossDetector.java
index 3619253..47425322 100644
--- a/services/core/java/com/android/server/vcn/routeselection/IpSecPacketLossDetector.java
+++ b/services/core/java/com/android/server/vcn/routeselection/IpSecPacketLossDetector.java
@@ -115,6 +115,10 @@
// validation failure.
private static final int IPSEC_PACKET_LOSS_PERCENT_THRESHOLD_DEFAULT = 12;
+ /** Carriers can disable the detector by setting the threshold to -1 */
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ static final int IPSEC_PACKET_LOSS_PERCENT_THRESHOLD_DISABLE_DETECTOR = -1;
+
private static final int POLL_IPSEC_STATE_INTERVAL_SECONDS_DEFAULT = 20;
// By default, there's no maximum limit enforced
@@ -271,7 +275,10 @@
// When multiple parallel inbound transforms are created, NetworkMetricMonitor will be
// enabled on the last one as a sample
mInboundTransform = inboundTransform;
- start();
+
+ if (!Flags.allowDisableIpsecLossDetector() || canStart()) {
+ start();
+ }
}
@Override
@@ -284,6 +291,14 @@
mPacketLossRatePercentThreshold = getPacketLossRatePercentThreshold(carrierConfig);
mMaxSeqNumIncreasePerSecond = getMaxSeqNumIncreasePerSecond(carrierConfig);
}
+
+ if (Flags.allowDisableIpsecLossDetector() && canStart() != isStarted()) {
+ if (canStart()) {
+ start();
+ } else {
+ stop();
+ }
+ }
}
@Override
@@ -298,6 +313,12 @@
mHandler.postDelayed(new PollIpSecStateRunnable(), mCancellationToken, 0L);
}
+ private boolean canStart() {
+ return mInboundTransform != null
+ && mPacketLossRatePercentThreshold
+ != IPSEC_PACKET_LOSS_PERCENT_THRESHOLD_DISABLE_DETECTOR;
+ }
+
@Override
protected void start() {
super.start();
diff --git a/services/core/java/com/android/server/vr/EnabledComponentsObserver.java b/services/core/java/com/android/server/vr/EnabledComponentsObserver.java
index 7126cb5..7c2ce64 100644
--- a/services/core/java/com/android/server/vr/EnabledComponentsObserver.java
+++ b/services/core/java/com/android/server/vr/EnabledComponentsObserver.java
@@ -110,7 +110,7 @@
final EnabledComponentsObserver o = new EnabledComponentsObserver(context, settingName,
servicePermission, serviceName, lock, listeners);
- PackageMonitor packageMonitor = new PackageMonitor() {
+ PackageMonitor packageMonitor = new PackageMonitor(true) {
@Override
public void onSomePackagesChanged() {
o.onPackagesChanged();
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperCropper.java b/services/core/java/com/android/server/wallpaper/WallpaperCropper.java
index b19bc7d..dd3d512 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperCropper.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperCropper.java
@@ -313,10 +313,14 @@
adjustedCrop.right -= widthToRemove / 2 + widthToRemove % 2;
}
} else {
- // TODO (b/281648899) the third case is not always correct, fix that.
+ // Note: the third case when MODE == BALANCE, -W + sqrt(W * H * R), is the width to add
+ // so that, when removing the appropriate height, we get a bitmap of aspect ratio R and
+ // total surface of W * H. In other words it is the width to add to get the desired
+ // aspect ratio R, while preserving the total number of pixels W * H.
int widthToAdd = mode == REMOVE ? 0
: mode == ADD ? (int) (0.5 + crop.height() * screenRatio - crop.width())
- : (int) (0.5 + crop.height() - crop.width());
+ : (int) (0.5 - crop.width()
+ + Math.sqrt(crop.width() * crop.height() * screenRatio));
int availableWidth = bitmapSize.x - crop.width();
if (availableWidth >= widthToAdd) {
int widthToAddLeft = widthToAdd / 2;
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index f1ba755..f8eb789 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -1346,6 +1346,10 @@
}
class MyPackageMonitor extends PackageMonitor {
+ private MyPackageMonitor() {
+ super(true);
+ }
+
@Override
public void onPackageUpdateFinished(String packageName, int uid) {
synchronized (mLock) {
@@ -3642,7 +3646,8 @@
}
// System wallpaper does not support multiple displays, attach this display to
// the fallback wallpaper.
- if (mFallbackWallpaper != null) {
+ if (mFallbackWallpaper != null && mFallbackWallpaper
+ .connection != null) {
final DisplayConnector connector = mFallbackWallpaper
.connection.getDisplayConnectorOrCreate(displayId);
if (connector == null) return;
diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java
index c5683f3..c9395da 100644
--- a/services/core/java/com/android/server/wm/ActivityClientController.java
+++ b/services/core/java/com/android/server/wm/ActivityClientController.java
@@ -957,6 +957,7 @@
public boolean enterPictureInPictureMode(IBinder token, final PictureInPictureParams params) {
final long origId = Binder.clearCallingIdentity();
try {
+ ensureSetPipAspectRatioQuotaTracker();
synchronized (mGlobalLock) {
final ActivityRecord r = ensureValidPictureInPictureActivityParams(
"enterPictureInPictureMode", token, params);
@@ -971,6 +972,7 @@
public void setPictureInPictureParams(IBinder token, final PictureInPictureParams params) {
final long origId = Binder.clearCallingIdentity();
try {
+ ensureSetPipAspectRatioQuotaTracker();
synchronized (mGlobalLock) {
final ActivityRecord r = ensureValidPictureInPictureActivityParams(
"setPictureInPictureParams", token, params);
@@ -1023,6 +1025,19 @@
}
/**
+ * Initialize the {@link #mSetPipAspectRatioQuotaTracker} if applicable, which should happen
+ * out of {@link #mGlobalLock} to avoid deadlock (AM lock is used in QuotaTrack ctor).
+ */
+ private void ensureSetPipAspectRatioQuotaTracker() {
+ if (mSetPipAspectRatioQuotaTracker == null) {
+ mSetPipAspectRatioQuotaTracker = new CountQuotaTracker(mContext,
+ Categorizer.SINGLE_CATEGORIZER);
+ mSetPipAspectRatioQuotaTracker.setCountLimit(Category.SINGLE_CATEGORY,
+ SET_PIP_ASPECT_RATIO_LIMIT, SET_PIP_ASPECT_RATIO_TIME_WINDOW_MS);
+ }
+ }
+
+ /**
* Checks the state of the system and the activity associated with the given {@param token} to
* verify that picture-in-picture is supported for that activity.
*
@@ -1049,12 +1064,6 @@
// Rate limit how frequent an app can request aspect ratio change via
// Activity#setPictureInPictureParams
final int userId = UserHandle.getCallingUserId();
- if (mSetPipAspectRatioQuotaTracker == null) {
- mSetPipAspectRatioQuotaTracker = new CountQuotaTracker(mContext,
- Categorizer.SINGLE_CATEGORIZER);
- mSetPipAspectRatioQuotaTracker.setCountLimit(Category.SINGLE_CATEGORY,
- SET_PIP_ASPECT_RATIO_LIMIT, SET_PIP_ASPECT_RATIO_TIME_WINDOW_MS);
- }
if (r.pictureInPictureArgs.hasSetAspectRatio()
&& params.hasSetAspectRatio()
&& !r.pictureInPictureArgs.getAspectRatio().equals(
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
index 6ec557a..b3208bf 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
@@ -88,6 +88,7 @@
import android.annotation.Nullable;
import android.app.ActivityOptions;
import android.app.ActivityOptions.SourceInfo;
+import android.app.ApplicationStartInfo;
import android.app.CameraCompatTaskInfo.CameraCompatControlState;
import android.app.WaitResult;
import android.app.WindowConfiguration.WindowingMode;
@@ -845,6 +846,16 @@
&& !r.mTransitionController.isCollecting(r))) {
done(false /* abort */, info, "notifyWindowsDrawn", timestampNs);
}
+
+ if (android.app.Flags.appStartInfoTimestamps()) {
+ // Log here to match StatsD for time to first frame.
+ mLoggerHandler.post(
+ () -> mSupervisor.mService.mWindowManager.mAmInternal.addStartInfoTimestamp(
+ ApplicationStartInfo.START_TIMESTAMP_FIRST_FRAME,
+ timestampNs, r.getUid(), r.getPid(),
+ info.mLastLaunchedActivity.mUserId));
+ }
+
return infoSnapshot;
}
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 7d057a9..e814f17 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -7846,10 +7846,12 @@
@Override
void prepareSurfaces() {
+ final boolean isDecorSurfaceBoosted =
+ getTask() != null && getTask().isDecorSurfaceBoosted();
final boolean show = (isVisible()
// Ensure that the activity content is hidden when the decor surface is boosted to
// prevent UI redressing attack.
- && !getTask().isDecorSurfaceBoosted())
+ && !isDecorSurfaceBoosted)
|| isAnimating(PARENTS, ANIMATION_TYPE_APP_TRANSITION | ANIMATION_TYPE_RECENTS
| ANIMATION_TYPE_PREDICT_BACK);
@@ -9492,6 +9494,12 @@
return false;
}
+ @Override
+ protected boolean setOverrideGender(Configuration requestsTmpConfig, int gender) {
+ return WindowProcessController.applyConfigGenderOverride(
+ requestsTmpConfig, gender, mAtmService.mGrammaticalManagerInternal, getUid());
+ }
+
@VisibleForTesting
@Override
Rect getAnimationBounds(int appRootTaskClipMode) {
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index fc05d17..5e95a4b 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -949,7 +949,7 @@
}
configuration.setGrammaticalGender(
- mGrammaticalManagerInternal.retrieveSystemGrammaticalGender(configuration));
+ mGrammaticalManagerInternal.mergedFinalSystemGrammaticalGender());
synchronized (mGlobalLock) {
mForceResizableActivities = forceResizable;
@@ -4381,7 +4381,8 @@
*/
protected boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name, String[] args,
int opti, boolean dumpAll, boolean dumpVisibleRootTasksOnly,
- boolean dumpFocusedRootTaskOnly, int displayIdFilter, @UserIdInt int userId) {
+ boolean dumpFocusedRootTaskOnly, int displayIdFilter, @UserIdInt int userId,
+ long timeout) {
ArrayList<ActivityRecord> activities;
synchronized (mGlobalLock) {
@@ -4426,7 +4427,7 @@
}
}
}
- dumpActivity(" ", fd, pw, activities.get(i), newArgs, dumpAll);
+ dumpActivity(" ", fd, pw, activities.get(i), newArgs, dumpAll, timeout);
}
if (!printedAnything) {
// Typically happpens when no task matches displayIdFilter
@@ -4440,7 +4441,7 @@
* there is a thread associated with the activity.
*/
private void dumpActivity(String prefix, FileDescriptor fd, PrintWriter pw,
- ActivityRecord r, String[] args, boolean dumpAll) {
+ ActivityRecord r, String[] args, boolean dumpAll, long timeout) {
String innerPrefix = prefix + " ";
IApplicationThread appThread = null;
synchronized (mGlobalLock) {
@@ -4471,7 +4472,7 @@
pw.flush();
try (TransferPipe tp = new TransferPipe()) {
appThread.dumpActivity(tp.getWriteFd(), r.token, innerPrefix, args);
- tp.go(fd);
+ tp.go(fd, timeout);
} catch (IOException e) {
pw.println(innerPrefix + "Failure while dumping the activity: " + e);
} catch (RemoteException e) {
@@ -6970,7 +6971,8 @@
boolean dumpFocusedRootTaskOnly, int displayIdFilter,
@UserIdInt int userId) {
return ActivityTaskManagerService.this.dumpActivity(fd, pw, name, args, opti, dumpAll,
- dumpVisibleRootTasksOnly, dumpFocusedRootTaskOnly, displayIdFilter, userId);
+ dumpVisibleRootTasksOnly, dumpFocusedRootTaskOnly, displayIdFilter, userId,
+ /* timeout= */ 5000);
}
@Override
diff --git a/services/core/java/com/android/server/wm/AsyncRotationController.java b/services/core/java/com/android/server/wm/AsyncRotationController.java
index e7fb265..24d4be8 100644
--- a/services/core/java/com/android/server/wm/AsyncRotationController.java
+++ b/services/core/java/com/android/server/wm/AsyncRotationController.java
@@ -288,6 +288,17 @@
final SurfaceControl.Transaction t = windowToken.getSyncTransaction();
clearTransform(t, op.mLeash);
}
+ // The insets position may be frozen by shouldFreezeInsetsPosition(), so refresh the
+ // position to the latest state when it is ready to show in new rotation.
+ if (mTransitionOp == OP_APP_SWITCH) {
+ for (int i = windowToken.getChildCount() - 1; i >= 0; i--) {
+ final WindowState w = windowToken.getChildAt(i);
+ final InsetsSourceProvider insetsProvider = w.getControllableInsetProvider();
+ if (insetsProvider != null) {
+ insetsProvider.updateInsetsControlPosition(w);
+ }
+ }
+ }
}
private static void clearTransform(SurfaceControl.Transaction t, SurfaceControl sc) {
diff --git a/services/core/java/com/android/server/wm/ConfigurationContainer.java b/services/core/java/com/android/server/wm/ConfigurationContainer.java
index 31754bf..efd5202 100644
--- a/services/core/java/com/android/server/wm/ConfigurationContainer.java
+++ b/services/core/java/com/android/server/wm/ConfigurationContainer.java
@@ -534,8 +534,8 @@
nightMode);
boolean newLocalesSet = (locales != null) && setOverrideLocales(mRequestsTmpConfig,
locales);
- boolean newGenderSet = (gender != null) && setOverrideGender(mRequestsTmpConfig,
- gender);
+ boolean newGenderSet = setOverrideGender(mRequestsTmpConfig,
+ gender == null ? Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED : gender);
if (newNightModeSet || newLocalesSet || newGenderSet) {
onRequestedOverrideConfigurationChanged(mRequestsTmpConfig);
}
@@ -577,14 +577,11 @@
*
* @return true if the grammatical gender has been changed.
*/
- private boolean setOverrideGender(Configuration requestsTmpConfig,
+ protected boolean setOverrideGender(Configuration requestsTmpConfig,
@Configuration.GrammaticalGender int gender) {
- if (mRequestedOverrideConfiguration.getGrammaticalGender() == gender) {
- return false;
- } else {
- requestsTmpConfig.setGrammaticalGender(gender);
- return true;
- }
+ // Noop, only ActivityRecord and WindowProcessController have enough knowledge about the
+ // app to apply gender correctly.
+ return false;
}
public boolean isActivityTypeDream() {
diff --git a/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java b/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java
index 1c59977..6aa0039 100644
--- a/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java
+++ b/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java
@@ -80,8 +80,8 @@
LaunchParamsController.LaunchParams outParams) {
if (!canEnterDesktopMode(mContext)) {
- appendLog("desktop mode is not enabled, continuing");
- return RESULT_CONTINUE;
+ appendLog("desktop mode is not enabled, skipping");
+ return RESULT_SKIP;
}
if (task == null) {
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 2f37e88..4147249 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -2738,6 +2738,10 @@
if (!mVisibleBackgroundUserEnabled) {
return true;
}
+ if (isPrivate()) {
+ // UserManager doesn't track the user visibility for private displays.
+ return true;
+ }
final int userId = UserHandle.getUserId(uid);
return userId == UserHandle.USER_SYSTEM
|| mWmService.mUmInternal.isUserVisible(userId, mDisplayId);
diff --git a/services/core/java/com/android/server/wm/InputConfigAdapter.java b/services/core/java/com/android/server/wm/InputConfigAdapter.java
index ef1b02d..119fafd 100644
--- a/services/core/java/com/android/server/wm/InputConfigAdapter.java
+++ b/services/core/java/com/android/server/wm/InputConfigAdapter.java
@@ -58,8 +58,8 @@
LayoutParams.INPUT_FEATURE_SPY,
InputConfig.SPY, false /* inverted */),
new FlagMapping(
- LayoutParams.INPUT_FEATURE_SENSITIVE_FOR_TRACING,
- InputConfig.SENSITIVE_FOR_TRACING, false /* inverted */));
+ LayoutParams.INPUT_FEATURE_SENSITIVE_FOR_PRIVACY,
+ InputConfig.SENSITIVE_FOR_PRIVACY, false /* inverted */));
@InputConfigFlags
private static final int INPUT_FEATURE_TO_CONFIG_MASK =
diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
index 8858766..4400ed2 100644
--- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
@@ -351,42 +351,47 @@
? windowState.wouldBeVisibleIfPolicyIgnored() && windowState.isVisibleByPolicy()
: mWindowContainer.isVisibleRequested();
setServerVisible(isServerVisible);
- if (mControl != null) {
- boolean changed = false;
- final Point position = getWindowFrameSurfacePosition();
- if (mControl.setSurfacePosition(position.x, position.y) && mControlTarget != null) {
- changed = true;
- if (windowState != null && windowState.getWindowFrames().didFrameSizeChange()
- && windowState.mWinAnimator.getShown() && mWindowContainer.okToDisplay()) {
- mHasPendingPosition = true;
- windowState.applyWithNextDraw(mSetLeashPositionConsumer);
- } else {
- Transaction t = mWindowContainer.getSyncTransaction();
- if (windowState != null) {
- // Make the buffer, token transformation, and leash position to be updated
- // together when the window is drawn for new rotation. Otherwise the window
- // may be outside the screen by the inconsistent orientations.
- final AsyncRotationController rotationController =
- mDisplayContent.getAsyncRotationController();
- if (rotationController != null) {
- final Transaction drawT =
- rotationController.getDrawTransaction(windowState.mToken);
- if (drawT != null) {
- t = drawT;
- }
+ updateInsetsControlPosition(windowState);
+ }
+
+ void updateInsetsControlPosition(WindowState windowState) {
+ if (mControl == null) {
+ return;
+ }
+ boolean changed = false;
+ final Point position = getWindowFrameSurfacePosition();
+ if (mControl.setSurfacePosition(position.x, position.y) && mControlTarget != null) {
+ changed = true;
+ if (windowState != null && windowState.getWindowFrames().didFrameSizeChange()
+ && windowState.mWinAnimator.getShown() && mWindowContainer.okToDisplay()) {
+ mHasPendingPosition = true;
+ windowState.applyWithNextDraw(mSetLeashPositionConsumer);
+ } else {
+ Transaction t = mWindowContainer.getSyncTransaction();
+ if (windowState != null) {
+ // Make the buffer, token transformation, and leash position to be updated
+ // together when the window is drawn for new rotation. Otherwise the window
+ // may be outside the screen by the inconsistent orientations.
+ final AsyncRotationController rotationController =
+ mDisplayContent.getAsyncRotationController();
+ if (rotationController != null) {
+ final Transaction drawT =
+ rotationController.getDrawTransaction(windowState.mToken);
+ if (drawT != null) {
+ t = drawT;
}
}
- mSetLeashPositionConsumer.accept(t);
}
+ mSetLeashPositionConsumer.accept(t);
}
- final Insets insetsHint = getInsetsHint();
- if (!mControl.getInsetsHint().equals(insetsHint)) {
- mControl.setInsetsHint(insetsHint);
- changed = true;
- }
- if (changed) {
- mStateController.notifyControlChanged(mControlTarget);
- }
+ }
+ final Insets insetsHint = getInsetsHint();
+ if (!mControl.getInsetsHint().equals(insetsHint)) {
+ mControl.setInsetsHint(insetsHint);
+ changed = true;
+ }
+ if (changed) {
+ mStateController.notifyControlChanged(mControlTarget);
}
}
diff --git a/services/core/java/com/android/server/wm/LetterboxConfiguration.java b/services/core/java/com/android/server/wm/LetterboxConfiguration.java
index 5aa0ed7..ce1a72d 100644
--- a/services/core/java/com/android/server/wm/LetterboxConfiguration.java
+++ b/services/core/java/com/android/server/wm/LetterboxConfiguration.java
@@ -25,7 +25,6 @@
import android.content.Context;
import android.graphics.Color;
import android.provider.DeviceConfig;
-import android.util.Slog;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
@@ -33,6 +32,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.function.Function;
+import java.util.function.IntSupplier;
/** Reads letterbox configs from resources and controls their overrides at runtime. */
final class LetterboxConfiguration {
@@ -265,6 +265,12 @@
// unresizable apps
private boolean mIsDisplayAspectRatioEnabledForFixedOrientationLetterbox;
+ // Supplier for the value in pixel to consider when detecting vertical thin letterboxing
+ private final IntSupplier mThinLetterboxWidthFn;
+
+ // Supplier for the value in pixel to consider when detecting horizontal thin letterboxing
+ private final IntSupplier mThinLetterboxHeightFn;
+
// Allows to enable letterboxing strategy for translucent activities ignoring flags.
private boolean mTranslucentLetterboxingOverrideEnabled;
@@ -358,6 +364,10 @@
R.bool.config_isWindowManagerCameraCompatSplitScreenAspectRatioEnabled);
mIsPolicyForIgnoringRequestedOrientationEnabled = mContext.getResources().getBoolean(
R.bool.config_letterboxIsPolicyForIgnoringRequestedOrientationEnabled);
+ mThinLetterboxWidthFn = () -> mContext.getResources().getDimensionPixelSize(
+ R.dimen.config_letterboxThinLetterboxWidthDp);
+ mThinLetterboxHeightFn = () -> mContext.getResources().getDimensionPixelSize(
+ R.dimen.config_letterboxThinLetterboxHeightDp);
mLetterboxConfigurationPersister = letterboxConfigurationPersister;
mLetterboxConfigurationPersister.start();
@@ -1129,6 +1139,24 @@
}
/**
+ * @return Width in pixel about the padding to use to understand if the letterbox for an
+ * activity is thin. If the available space has width W and the app has width w, this
+ * is the maximum value for (W - w) / 2 to be considered for a thin letterboxed app.
+ */
+ int getThinLetterboxWidthPx() {
+ return mThinLetterboxWidthFn.getAsInt();
+ }
+
+ /**
+ * @return Height in pixel about the padding to use to understand if a letterbox is thin.
+ * If the available space has height H and the app has height h, this is the maximum
+ * value for (H - h) / 2 to be considered for a thin letterboxed app.
+ */
+ int getThinLetterboxHeightPx() {
+ return mThinLetterboxHeightFn.getAsInt();
+ }
+
+ /**
* Overrides whether using split screen aspect ratio as a default aspect ratio for unresizable
* apps.
*/
diff --git a/services/core/java/com/android/server/wm/LetterboxUiController.java b/services/core/java/com/android/server/wm/LetterboxUiController.java
index b38e666..9e16b8a 100644
--- a/services/core/java/com/android/server/wm/LetterboxUiController.java
+++ b/services/core/java/com/android/server/wm/LetterboxUiController.java
@@ -1024,6 +1024,67 @@
return getSplitScreenAspectRatio();
}
+ /**
+ * @return {@value true} if the resulting app is letterboxed in a way defined as thin.
+ */
+ boolean isVerticalThinLetterboxed() {
+ final int thinHeight = mLetterboxConfiguration.getThinLetterboxHeightPx();
+ if (thinHeight < 0) {
+ return false;
+ }
+ final Task task = mActivityRecord.getTask();
+ if (task == null) {
+ return false;
+ }
+ final int padding = Math.abs(
+ task.getBounds().height() - mActivityRecord.getBounds().height()) / 2;
+ return padding <= thinHeight;
+ }
+
+ /**
+ * @return {@value true} if the resulting app is pillarboxed in a way defined as thin.
+ */
+ boolean isHorizontalThinLetterboxed() {
+ final int thinWidth = mLetterboxConfiguration.getThinLetterboxWidthPx();
+ if (thinWidth < 0) {
+ return false;
+ }
+ final Task task = mActivityRecord.getTask();
+ if (task == null) {
+ return false;
+ }
+ final int padding = Math.abs(
+ task.getBounds().width() - mActivityRecord.getBounds().width()) / 2;
+ return padding <= thinWidth;
+ }
+
+
+ /**
+ * @return {@value true} if the vertical reachability should be allowed in case of
+ * thin letteboxing
+ */
+ boolean allowVerticalReachabilityForThinLetterbox() {
+ if (!Flags.disableThinLetterboxingReachability()) {
+ return true;
+ }
+ // When the flag is enabled we allow vertical reachability only if the
+ // app is not thin letterboxed vertically.
+ return !isVerticalThinLetterboxed();
+ }
+
+ /**
+ * @return {@value true} if the vertical reachability should be enabled in case of
+ * thin letteboxing
+ */
+ boolean allowHorizontalReachabilityForThinLetterbox() {
+ if (!Flags.disableThinLetterboxingReachability()) {
+ return true;
+ }
+ // When the flag is enabled we allow horizontal reachability only if the
+ // app is not thin pillarboxed.
+ return !isHorizontalThinLetterboxed();
+ }
+
float getSplitScreenAspectRatio() {
// Getting the same aspect ratio that apps get in split screen.
final DisplayArea displayArea = mActivityRecord.getDisplayArea();
@@ -1263,6 +1324,9 @@
* </ul>
*/
private boolean isHorizontalReachabilityEnabled(Configuration parentConfiguration) {
+ if (!allowHorizontalReachabilityForThinLetterbox()) {
+ return false;
+ }
// Use screen resolved bounds which uses resolved bounds or size compat bounds
// as activity bounds can sometimes be empty
final Rect opaqueActivityBounds = hasInheritedLetterboxBehavior()
@@ -1298,6 +1362,9 @@
* </ul>
*/
private boolean isVerticalReachabilityEnabled(Configuration parentConfiguration) {
+ if (!allowVerticalReachabilityForThinLetterbox()) {
+ return false;
+ }
// Use screen resolved bounds which uses resolved bounds or size compat bounds
// as activity bounds can sometimes be empty
final Rect opaqueActivityBounds = hasInheritedLetterboxBehavior()
@@ -1566,6 +1633,8 @@
if (!shouldShowLetterboxUi) {
return;
}
+ pw.println(prefix + " isVerticalThinLetterboxed=" + isVerticalThinLetterboxed());
+ pw.println(prefix + " isHorizontalThinLetterboxed=" + isHorizontalThinLetterboxed());
pw.println(prefix + " letterboxBackgroundColor=" + Integer.toHexString(
getLetterboxBackgroundColor().toArgb()));
pw.println(prefix + " letterboxBackgroundType="
diff --git a/services/core/java/com/android/server/wm/OWNERS b/services/core/java/com/android/server/wm/OWNERS
index ce47f5c..60454fc 100644
--- a/services/core/java/com/android/server/wm/OWNERS
+++ b/services/core/java/com/android/server/wm/OWNERS
@@ -18,6 +18,7 @@
yunfanc@google.com
wilsonshih@google.com
jiamingliu@google.com
+pdwilliams@google.com
# Files related to background activity launches
per-file Background*Start* = set noparent
diff --git a/services/core/java/com/android/server/wm/PackageConfigPersister.java b/services/core/java/com/android/server/wm/PackageConfigPersister.java
index 23127ac..9d597ea 100644
--- a/services/core/java/com/android/server/wm/PackageConfigPersister.java
+++ b/services/core/java/com/android/server/wm/PackageConfigPersister.java
@@ -169,6 +169,8 @@
LocaleOverlayHelper.combineLocalesIfOverlayExists(
modifiedRecord.mLocales, mAtm.getGlobalConfiguration().getLocales()),
modifiedRecord.mGrammaticalGender);
+ } else {
+ container.applyAppSpecificConfig(null, null, null);
}
}
}
diff --git a/services/core/java/com/android/server/wm/RecentTasks.java b/services/core/java/com/android/server/wm/RecentTasks.java
index 8e78d25..6dec712 100644
--- a/services/core/java/com/android/server/wm/RecentTasks.java
+++ b/services/core/java/com/android/server/wm/RecentTasks.java
@@ -708,26 +708,6 @@
}
}
- /**
- * Removes the oldest recent task that is compatible with the given one. This is possible if
- * the task windowing mode changed after being added to the Recents.
- */
- void removeCompatibleRecentTask(Task task) {
- final int taskIndex = mTasks.indexOf(task);
- if (taskIndex < 0) {
- return;
- }
-
- final int candidateIndex = findRemoveIndexForTask(task, false /* includingSelf */);
- if (candidateIndex == -1) {
- // Nothing to trim
- return;
- }
-
- final Task taskToRemove = taskIndex > candidateIndex ? task : mTasks.get(candidateIndex);
- remove(taskToRemove);
- }
-
void removeTasksByPackageName(String packageName, int userId) {
for (int i = mTasks.size() - 1; i >= 0; --i) {
final Task task = mTasks.get(i);
@@ -1615,10 +1595,6 @@
* list (if any).
*/
private int findRemoveIndexForAddTask(Task task) {
- return findRemoveIndexForTask(task, true /* includingSelf */);
- }
-
- private int findRemoveIndexForTask(Task task, boolean includingSelf) {
final int recentsCount = mTasks.size();
final Intent intent = task.intent;
final boolean document = intent != null && intent.isDocument();
@@ -1674,8 +1650,6 @@
// existing task
continue;
}
- } else if (!includingSelf) {
- continue;
}
return i;
}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 301d0a5..8bd7b5f 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -20,7 +20,6 @@
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.app.ActivityTaskManager.INVALID_WINDOWING_MODE;
import static android.app.ActivityTaskManager.RESIZE_MODE_FORCED;
-import static android.app.ActivityTaskManager.RESIZE_MODE_SYSTEM_SCREEN_ROTATION;
import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SPLIT_SCREEN;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
@@ -47,7 +46,6 @@
import static android.provider.Settings.Secure.USER_SETUP_COMPLETE;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
-import static android.view.InsetsSource.FLAG_INSETS_ROUNDED_CORNER;
import static android.view.SurfaceControl.METADATA_TASK_ID;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
@@ -170,12 +168,9 @@
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
import android.view.DisplayInfo;
-import android.view.InsetsSource;
import android.view.InsetsState;
import android.view.RemoteAnimationAdapter;
-import android.view.Surface;
import android.view.SurfaceControl;
-import android.view.TaskTransitionSpec;
import android.view.WindowManager;
import android.view.WindowManager.TransitionOldType;
import android.window.ITaskOrganizer;
@@ -365,6 +360,10 @@
* user wants to return to it. */
private WindowProcessController mRootProcess;
+ /** The TF host info are set once the task has ever added an organized task fragment. */
+ int mTaskFragmentHostUid;
+ String mTaskFragmentHostProcessName;
+
/** Takes on same value as first root activity */
boolean isPersistable = false;
int maxRecents;
@@ -441,16 +440,6 @@
// Id of the previous display the root task was on.
int mPrevDisplayId = INVALID_DISPLAY;
- /** ID of the display which rotation {@link #mRotation} has. */
- private int mLastRotationDisplayId = INVALID_DISPLAY;
-
- /**
- * Display rotation as of the last time {@link #setBounds(Rect)} was called or this task was
- * moved to a new display.
- */
- @Surface.Rotation
- private int mRotation;
-
int mMultiWindowRestoreWindowingMode = INVALID_WINDOWING_MODE;
/**
@@ -461,10 +450,7 @@
*/
int mLastReportedRequestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
- // For comparison with DisplayContent bounds.
- private Rect mTmpRect = new Rect();
- // For handling display rotations.
- private Rect mTmpRect2 = new Rect();
+ private final Rect mTmpRect = new Rect();
// Resize mode of the task. See {@link ActivityInfo#resizeMode}
// Based on the {@link ActivityInfo#resizeMode} of the root activity.
@@ -1197,9 +1183,6 @@
updateOverrideConfigurationFromLaunchBounds();
}
- // Update task bounds if needed.
- adjustBoundsForDisplayChangeIfNeeded(getDisplayContent());
-
mRootWindowContainer.updateUIDsPresentOnDisplay();
// Ensure all animations are finished at same time in split-screen mode.
@@ -1471,6 +1454,11 @@
// passed from Task constructor.
final TaskFragment childTaskFrag = child.asTaskFragment();
if (childTaskFrag != null && childTaskFrag.asTask() == null) {
+ if (childTaskFrag.mTaskFragmentOrganizerProcessName != null
+ && mTaskFragmentHostProcessName == null) {
+ mTaskFragmentHostUid = childTaskFrag.mTaskFragmentOrganizerUid;
+ mTaskFragmentHostProcessName = childTaskFrag.mTaskFragmentOrganizerProcessName;
+ }
childTaskFrag.setMinDimensions(mMinWidth, mMinHeight);
// The starting window should keep covering its task when a pure TaskFragment is added
@@ -2734,15 +2722,7 @@
return setBounds(getRequestedOverrideBounds(), bounds);
}
- int rotation = Surface.ROTATION_0;
- final DisplayContent displayContent = getRootTask() != null
- ? getRootTask().getDisplayContent() : null;
- if (displayContent != null) {
- rotation = displayContent.getDisplayInfo().rotation;
- }
-
final int boundsChange = super.setBounds(bounds);
- mRotation = rotation;
updateSurfacePositionNonOrganized();
return boundsChange;
}
@@ -2802,10 +2782,6 @@
@Override
void onDisplayChanged(DisplayContent dc) {
- final boolean isRootTask = isRootTask();
- if (!isRootTask && !mCreatedByOrganizer) {
- adjustBoundsForDisplayChangeIfNeeded(dc);
- }
super.onDisplayChanged(dc);
if (isLeafTask()) {
final int displayId = (dc != null) ? dc.getDisplayId() : INVALID_DISPLAY;
@@ -2939,33 +2915,6 @@
return;
}
- /**
- * Account for specified insets to crop the animation bounds by to avoid the animation
- * occurring over "out of bounds" regions
- *
- * For example this is used to make sure the tasks are cropped to be fully above the expanded
- * taskbar when animating.
- *
- * TEMPORARY FIELD (b/202383002)
- * TODO: Remove once we use surfaceflinger rounded corners on tasks rather than taskbar overlays
- * or when shell transitions are fully enabled
- *
- * @param animationBounds The animation bounds to adjust to account for the custom spec insets.
- */
- void adjustAnimationBoundsForTransition(Rect animationBounds) {
- TaskTransitionSpec spec = mWmService.mTaskTransitionSpec;
- if (spec != null) {
- final InsetsState state =
- getDisplayContent().getInsetsStateController().getRawInsetsState();
- for (int i = state.sourceSize() - 1; i >= 0; i--) {
- final InsetsSource source = state.sourceAt(i);
- if (source.hasFlags(FLAG_INSETS_ROUNDED_CORNER)) {
- animationBounds.inset(source.calculateVisibleInsets(animationBounds));
- }
- }
- }
- }
-
void setDragResizing(boolean dragResizing) {
if (mDragResizing != dragResizing) {
// No need to check if allowed if it's leaving dragResize
@@ -2983,48 +2932,6 @@
return mDragResizing;
}
- void adjustBoundsForDisplayChangeIfNeeded(final DisplayContent displayContent) {
- if (displayContent == null) {
- return;
- }
- if (getRequestedOverrideBounds().isEmpty()) {
- return;
- }
- final int displayId = displayContent.getDisplayId();
- final int newRotation = displayContent.getDisplayInfo().rotation;
- if (displayId != mLastRotationDisplayId) {
- // This task is on a display that it wasn't on. There is no point to keep the relative
- // position if display rotations for old and new displays are different. Just keep these
- // values.
- mLastRotationDisplayId = displayId;
- mRotation = newRotation;
- return;
- }
-
- if (mRotation == newRotation) {
- // Rotation didn't change. We don't need to adjust the bounds to keep the relative
- // position.
- return;
- }
-
- // Device rotation changed.
- // - We don't want the task to move around on the screen when this happens, so update the
- // task bounds so it stays in the same place.
- // - Rotate the bounds and notify activity manager if the task can be resized independently
- // from its root task. The root task will take care of task rotation for the other case.
- mTmpRect2.set(getBounds());
-
- if (!getWindowConfiguration().canResizeTask()) {
- setBounds(mTmpRect2);
- return;
- }
-
- displayContent.rotateBounds(mRotation, newRotation, mTmpRect2);
- if (setBounds(mTmpRect2) != BOUNDS_CHANGE_NONE) {
- mAtmService.resizeTask(mTaskId, getBounds(), RESIZE_MODE_SYSTEM_SCREEN_ROTATION);
- }
- }
-
/** Cancels any running app transitions associated with the task. */
void cancelTaskWindowTransition() {
for (int i = mChildren.size() - 1; i >= 0; --i) {
@@ -3206,6 +3113,11 @@
mTaskId, snapshot);
}
+ void onSnapshotInvalidated() {
+ mAtmService.getTaskChangeNotificationController().notifyTaskSnapshotInvalidated(mTaskId);
+ }
+
+
TaskDescription getTaskDescription() {
return mTaskDescription;
}
@@ -3550,8 +3462,6 @@
info.isVisibleRequested = isVisibleRequested();
info.isSleeping = shouldSleepActivities();
info.isTopActivityTransparent = top != null && !top.fillsParent();
- appCompatTaskInfo.isLetterboxDoubleTapEnabled = top != null
- && top.mLetterboxUiController.isLetterboxDoubleTapEducationEnabled();
appCompatTaskInfo.topActivityLetterboxVerticalPosition = TaskInfo.PROPERTY_VALUE_UNSET;
appCompatTaskInfo.topActivityLetterboxHorizontalPosition = TaskInfo.PROPERTY_VALUE_UNSET;
appCompatTaskInfo.topActivityLetterboxWidth = TaskInfo.PROPERTY_VALUE_UNSET;
@@ -3566,15 +3476,29 @@
appCompatTaskInfo.topActivityLetterboxWidth = top.getBounds().width();
appCompatTaskInfo.topActivityLetterboxHeight = top.getBounds().height();
}
+ // We need to consider if letterboxed or pillarboxed
+ // TODO(b/336807329) Encapsulate reachability logic
+ appCompatTaskInfo.isLetterboxDoubleTapEnabled = top != null
+ && top.mLetterboxUiController.isLetterboxDoubleTapEducationEnabled();
if (appCompatTaskInfo.isLetterboxDoubleTapEnabled) {
if (appCompatTaskInfo.isTopActivityPillarboxed()) {
- // Pillarboxed
- appCompatTaskInfo.topActivityLetterboxHorizontalPosition =
- top.mLetterboxUiController.getLetterboxPositionForHorizontalReachability();
+ if (top.mLetterboxUiController.allowHorizontalReachabilityForThinLetterbox()) {
+ // Pillarboxed
+ appCompatTaskInfo.topActivityLetterboxHorizontalPosition =
+ top.mLetterboxUiController
+ .getLetterboxPositionForHorizontalReachability();
+ } else {
+ appCompatTaskInfo.isLetterboxDoubleTapEnabled = false;
+ }
} else {
- // Letterboxed
- appCompatTaskInfo.topActivityLetterboxVerticalPosition =
- top.mLetterboxUiController.getLetterboxPositionForVerticalReachability();
+ if (top.mLetterboxUiController.allowVerticalReachabilityForThinLetterbox()) {
+ // Letterboxed
+ appCompatTaskInfo.topActivityLetterboxVerticalPosition =
+ top.mLetterboxUiController
+ .getLetterboxPositionForVerticalReachability();
+ } else {
+ appCompatTaskInfo.isLetterboxDoubleTapEnabled = false;
+ }
}
}
appCompatTaskInfo.topActivityEligibleForUserAspectRatioButton = top != null
@@ -6913,7 +6837,7 @@
mIsBoosted = isBoosted;
// The client transaction will be applied together with the next assignLayer.
if (clientTransaction != null) {
- mDecorSurfaceContainer.mPendingClientTransactions.add(clientTransaction);
+ mPendingClientTransactions.add(clientTransaction);
}
}
diff --git a/services/core/java/com/android/server/wm/TaskChangeNotificationController.java b/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
index 9324e29..21e7a8d 100644
--- a/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
+++ b/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
@@ -61,6 +61,7 @@
private static final int NOTIFY_ACTIVITY_ROTATED_MSG = 26;
private static final int NOTIFY_TASK_MOVED_TO_BACK_LISTENERS_MSG = 27;
private static final int NOTIFY_LOCK_TASK_MODE_CHANGED_MSG = 28;
+ private static final int NOTIFY_TASK_SNAPSHOT_INVALIDATED_LISTENERS_MSG = 29;
// Delay in notifying task stack change listeners (in millis)
private static final int NOTIFY_TASK_STACK_CHANGE_LISTENERS_DELAY = 100;
@@ -150,6 +151,9 @@
private final TaskStackConsumer mNotifyTaskSnapshotChanged = (l, m) -> {
l.onTaskSnapshotChanged(m.arg1, (TaskSnapshot) m.obj);
};
+ private final TaskStackConsumer mNotifyTaskSnapshotInvalidated = (l, m) -> {
+ l.onTaskSnapshotInvalidated(m.arg1);
+ };
private final TaskStackConsumer mNotifyTaskDisplayChanged = (l, m) -> {
l.onTaskDisplayChanged(m.arg1, m.arg2);
@@ -271,6 +275,9 @@
case NOTIFY_LOCK_TASK_MODE_CHANGED_MSG:
forAllRemoteListeners(mNotifyLockTaskModeChanged, msg);
break;
+ case NOTIFY_TASK_SNAPSHOT_INVALIDATED_LISTENERS_MSG:
+ forAllRemoteListeners(mNotifyTaskSnapshotInvalidated, msg);
+ break;
}
if (msg.obj instanceof SomeArgs) {
((SomeArgs) msg.obj).recycle();
@@ -485,6 +492,16 @@
}
/**
+ * Notify listeners that the snapshot of a task is invalidated.
+ */
+ void notifyTaskSnapshotInvalidated(int taskId) {
+ final Message msg = mHandler.obtainMessage(NOTIFY_TASK_SNAPSHOT_INVALIDATED_LISTENERS_MSG,
+ taskId, 0 /* unused */);
+ forAllLocalListeners(mNotifyTaskSnapshotInvalidated, msg);
+ msg.sendToTarget();
+ }
+
+ /**
* Notify listeners that an activity received a back press when there are no other activities
* in the back stack.
*/
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index 2b631f7..6a7f60b 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -320,9 +320,9 @@
/** Organizer that organizing this TaskFragment. */
@Nullable
private ITaskFragmentOrganizer mTaskFragmentOrganizer;
- @VisibleForTesting
+
int mTaskFragmentOrganizerUid = INVALID_UID;
- private @Nullable String mTaskFragmentOrganizerProcessName;
+ @Nullable String mTaskFragmentOrganizerProcessName;
/** Client assigned unique token for this TaskFragment if this is created by an organizer. */
@Nullable
@@ -485,14 +485,16 @@
*/
@Nullable
private WindowProcessController getOrganizerProcessIfDifferent(@Nullable ActivityRecord r) {
- if ((r == null || mTaskFragmentOrganizerProcessName == null)
- || (mTaskFragmentOrganizerProcessName.equals(r.processName)
- && mTaskFragmentOrganizerUid == r.getUid())) {
- // No organizer or the process is the same.
+ final Task task = getTask();
+ if (r == null || task == null || task.mTaskFragmentHostProcessName == null) {
return null;
}
- return mAtmService.getProcessController(mTaskFragmentOrganizerProcessName,
- mTaskFragmentOrganizerUid);
+ if (task.mTaskFragmentHostProcessName.equals(r.processName)
+ && task.mTaskFragmentHostUid == r.getUid()) {
+ return null;
+ }
+ return mAtmService.getProcessController(task.mTaskFragmentHostProcessName,
+ task.mTaskFragmentHostUid);
}
void setAnimationParams(@NonNull TaskFragmentAnimationParams animationParams) {
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index cb8304c..d70ca02 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -44,7 +44,6 @@
import static com.android.server.wm.AppTransition.MAX_APP_TRANSITION_DURATION;
import static com.android.server.wm.AppTransition.isActivityTransitOld;
import static com.android.server.wm.AppTransition.isTaskFragmentTransitOld;
-import static com.android.server.wm.AppTransition.isTaskTransitOld;
import static com.android.server.wm.DisplayContent.IME_TARGET_LAYERING;
import static com.android.server.wm.IdentifierProto.HASH_CODE;
import static com.android.server.wm.IdentifierProto.TITLE;
@@ -72,7 +71,6 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.ActivityInfo.ScreenOrientation;
import android.content.res.Configuration;
@@ -103,7 +101,6 @@
import android.view.SurfaceControl.Builder;
import android.view.SurfaceControlViewHost;
import android.view.SurfaceSession;
-import android.view.TaskTransitionSpec;
import android.view.WindowManager;
import android.view.WindowManager.TransitionOldType;
import android.view.animation.Animation;
@@ -3146,9 +3143,6 @@
// Separate position and size for use in animators.
final Rect screenBounds = getAnimationBounds(appRootTaskClipMode);
mTmpRect.set(screenBounds);
- if (this.asTask() != null && isTaskTransitOld(transit)) {
- this.asTask().adjustAnimationBoundsForTransition(mTmpRect);
- }
getAnimationPosition(mTmpPoint);
mTmpRect.offsetTo(0, 0);
@@ -3283,10 +3277,6 @@
AnimationRunnerBuilder animationRunnerBuilder = new AnimationRunnerBuilder();
- if (isTaskTransitOld(transit) && getWindowingMode() == WINDOWING_MODE_FULLSCREEN) {
- animationRunnerBuilder.setTaskBackgroundColor(getTaskAnimationBackgroundColor());
- }
-
// Check if the animation requests to show background color for Activity and embedded
// TaskFragment.
final ActivityRecord activityRecord = asActivityRecord();
@@ -3340,18 +3330,6 @@
}
}
- private @ColorInt int getTaskAnimationBackgroundColor() {
- Context uiContext = mDisplayContent.getDisplayPolicy().getSystemUiContext();
- TaskTransitionSpec customSpec = mWmService.mTaskTransitionSpec;
- @ColorInt int defaultFallbackColor = uiContext.getColor(R.color.overview_background);
-
- if (customSpec != null && customSpec.backgroundColor != 0) {
- return customSpec.backgroundColor;
- }
-
- return defaultFallbackColor;
- }
-
final SurfaceAnimationRunner getSurfaceAnimationRunner() {
return mWmService.mSurfaceAnimationRunner;
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java
index eeedec3..19053f7 100644
--- a/services/core/java/com/android/server/wm/WindowManagerInternal.java
+++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java
@@ -306,6 +306,18 @@
}
/**
+ * An interface to be notified on window removal.
+ */
+ public interface OnWindowRemovedListener {
+ /**
+ * Called when a window is removed.
+ *
+ * @param token the client token
+ */
+ void onWindowRemoved(IBinder token);
+ }
+
+ /**
* An interface to be notified when keyguard exit animation should start.
*/
public interface KeyguardExitAnimationStartListener {
@@ -1076,6 +1088,20 @@
public abstract void clearBlockedApps();
/**
+ * Register a listener to receive a callback on window removal.
+ *
+ * @param listener the listener to be registered.
+ */
+ public abstract void registerOnWindowRemovedListener(OnWindowRemovedListener listener);
+
+ /**
+ * Removes the listener.
+ *
+ * @param listener the listener to be removed.
+ */
+ public abstract void unregisterOnWindowRemovedListener(OnWindowRemovedListener listener);
+
+ /**
* Moves the current focus to the adjacent activity if it has the latest created window.
*/
public abstract boolean moveFocusToAdjacentEmbeddedActivityIfNeeded();
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index b19f0be..dbe3d36 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -20,7 +20,6 @@
import static android.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS;
import static android.Manifest.permission.INPUT_CONSUMER;
import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
-import static android.Manifest.permission.MANAGE_ACTIVITY_TASKS;
import static android.Manifest.permission.MANAGE_APP_TOKENS;
import static android.Manifest.permission.MODIFY_TOUCH_MODE_STATE;
import static android.Manifest.permission.READ_FRAME_BUFFER;
@@ -45,6 +44,7 @@
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.permission.flags.Flags.sensitiveContentImprovements;
import static android.permission.flags.Flags.sensitiveContentMetricsBugfix;
+import static android.permission.flags.Flags.sensitiveContentRecentsScreenshotBugfix;
import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT;
import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_NON_RESIZABLE_MULTI_WINDOW;
import static android.provider.Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS;
@@ -54,6 +54,7 @@
import static android.view.ContentRecordingSession.RECORD_CONTENT_TASK;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
+import static android.view.flags.Flags.sensitiveContentAppProtection;
import static android.view.WindowManager.DISPLAY_IME_POLICY_FALLBACK_DISPLAY;
import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
@@ -68,7 +69,7 @@
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
import static android.view.WindowManager.LayoutParams.FLAG_SLIPPERY;
import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
-import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_SENSITIVE_FOR_TRACING;
+import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_SENSITIVE_FOR_PRIVACY;
import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_SPY;
import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE;
import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
@@ -148,6 +149,7 @@
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_VERBOSE_TRANSACTIONS;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+import static com.android.server.wm.WindowManagerInternal.OnWindowRemovedListener;
import static com.android.server.wm.WindowManagerServiceDumpProto.BACK_NAVIGATION;
import static com.android.server.wm.WindowManagerServiceDumpProto.DISPLAY_FROZEN;
import static com.android.server.wm.WindowManagerServiceDumpProto.FOCUSED_APP;
@@ -295,7 +297,6 @@
import android.view.SurfaceControl;
import android.view.SurfaceControlViewHost;
import android.view.SurfaceSession;
-import android.view.TaskTransitionSpec;
import android.view.View;
import android.view.View.FocusDirection;
import android.view.ViewDebug;
@@ -491,6 +492,9 @@
private final RemoteCallbackList<IKeyguardLockedStateListener> mKeyguardLockedStateListeners =
new RemoteCallbackList<>();
+
+ private final List<OnWindowRemovedListener> mOnWindowRemovedListeners = new ArrayList<>();
+
private boolean mDispatchedKeyguardLockedState = false;
// VR Vr2d Display Id.
@@ -536,6 +540,21 @@
}
@Override
+ public void dumpHigh(FileDescriptor fd, PrintWriter pw, String[] args,
+ boolean asProto) {
+ if (asProto) {
+ return;
+ }
+ mAtmService.dumpActivity(fd, pw, /* name= */ "all", /* args= */ new String[]{},
+ /* opti= */ 0,
+ /* dumpAll= */ true,
+ /* dumpVisibleRootTasksOnly= */ true,
+ /* dumpFocusedRootTaskOnly= */ false, INVALID_DISPLAY, UserHandle.USER_ALL,
+ /* timeout= */ 1000
+ );
+ }
+
+ @Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args, boolean asProto) {
doDump(fd, pw, args, asProto);
}
@@ -763,11 +782,6 @@
*/
final Handler mAnimationHandler = new Handler(AnimationThread.getHandler().getLooper());
- /**
- * Used during task transitions to allow SysUI and launcher to customize task transitions.
- */
- TaskTransitionSpec mTaskTransitionSpec;
-
boolean mHardKeyboardAvailable;
WindowManagerInternal.OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener;
@@ -2080,7 +2094,11 @@
*/
void postWindowRemoveCleanupLocked(WindowState win) {
ProtoLog.v(WM_DEBUG_ADD_REMOVE, "postWindowRemoveCleanupLocked: %s", win);
- mWindowMap.remove(win.mClient.asBinder());
+ final IBinder client = win.mClient.asBinder();
+ mWindowMap.remove(client);
+ if (sensitiveContentAppProtection()) {
+ notifyWindowRemovedListeners(client);
+ }
final DisplayContent dc = win.getDisplayContent();
dc.getDisplayRotation().markForSeamlessRotation(win, false /* seamlesslyRotated */);
@@ -5342,6 +5360,23 @@
}
}
+ private void notifyWindowRemovedListeners(IBinder client) {
+ OnWindowRemovedListener[] windowRemovedListeners;
+ synchronized (mGlobalLock) {
+ if (mOnWindowRemovedListeners.isEmpty()) {
+ return;
+ }
+ windowRemovedListeners = new OnWindowRemovedListener[mOnWindowRemovedListeners.size()];
+ mOnWindowRemovedListeners.toArray(windowRemovedListeners);
+ }
+ mH.post(() -> {
+ int size = windowRemovedListeners.length;
+ for (int i = 0; i < size; i++) {
+ windowRemovedListeners[i].onWindowRemoved(client);
+ }
+ });
+ }
+
private void notifyWindowsChanged() {
WindowChangeListener[] windowChangeListeners;
synchronized (mGlobalLock) {
@@ -8834,6 +8869,14 @@
mRoot.forAllWindows((w) -> {
if (w.isVisible()) {
WindowManagerService.this.showToastIfBlockingScreenCapture(w);
+ } else if (sensitiveContentRecentsScreenshotBugfix()
+ && shouldInvalidateSnapshot(w)) {
+ final Task task = w.getTask();
+ // preventing from showing up in starting window.
+ mTaskSnapshotController.removeAndDeleteSnapshot(
+ task.mTaskId, task.mUserId);
+ // Refresh TaskThumbnailCache
+ task.onSnapshotInvalidated();
}
}, /* traverseTopToBottom= */ true);
}
@@ -8841,6 +8884,12 @@
}
}
+ private boolean shouldInvalidateSnapshot(WindowState w) {
+ return w.getTask() != null
+ && mSensitiveContentPackages.shouldBlockScreenCaptureForApp(
+ w.getOwningPackage(), w.getOwningUid(), w.getWindowToken());
+ }
+
@Override
public void removeBlockScreenCaptureForApps(ArraySet<PackageInfo> packageInfos) {
synchronized (mGlobalLock) {
@@ -8875,6 +8924,20 @@
}
@Override
+ public void registerOnWindowRemovedListener(OnWindowRemovedListener listener) {
+ synchronized (mGlobalLock) {
+ mOnWindowRemovedListeners.add(listener);
+ }
+ }
+
+ @Override
+ public void unregisterOnWindowRemovedListener(OnWindowRemovedListener listener) {
+ synchronized (mGlobalLock) {
+ mOnWindowRemovedListeners.remove(listener);
+ }
+ }
+
+ @Override
public boolean moveFocusToAdjacentEmbeddedActivityIfNeeded() {
synchronized (mGlobalLock) {
final WindowState focusedWindow = getFocusedWindow();
@@ -9248,11 +9311,11 @@
}
}
- // You can only use INPUT_FEATURE_SENSITIVE_FOR_TRACING on a trusted overlay.
- if ((inputFeatures & INPUT_FEATURE_SENSITIVE_FOR_TRACING) != 0 && !isTrustedOverlay) {
- Slog.w(TAG, "Removing INPUT_FEATURE_SENSITIVE_FOR_TRACING from '" + windowName
+ // You can only use INPUT_FEATURE_SENSITIVE_FOR_PRIVACY on a trusted overlay.
+ if ((inputFeatures & INPUT_FEATURE_SENSITIVE_FOR_PRIVACY) != 0 && !isTrustedOverlay) {
+ Slog.w(TAG, "Removing INPUT_FEATURE_SENSITIVE_FOR_PRIVACY from '" + windowName
+ "' because it isn't a trusted overlay");
- return inputFeatures & ~INPUT_FEATURE_SENSITIVE_FOR_TRACING;
+ return inputFeatures & ~INPUT_FEATURE_SENSITIVE_FOR_PRIVACY;
}
return inputFeatures;
}
@@ -9932,24 +9995,6 @@
}
@Override
- public void setTaskTransitionSpec(TaskTransitionSpec spec) {
- if (!checkCallingPermission(MANAGE_ACTIVITY_TASKS, "setTaskTransitionSpec()")) {
- throw new SecurityException("Requires MANAGE_ACTIVITY_TASKS permission");
- }
-
- mTaskTransitionSpec = spec;
- }
-
- @Override
- public void clearTaskTransitionSpec() {
- if (!checkCallingPermission(MANAGE_ACTIVITY_TASKS, "clearTaskTransitionSpec()")) {
- throw new SecurityException("Requires MANAGE_ACTIVITY_TASKS permission");
- }
-
- mTaskTransitionSpec = null;
- }
-
- @Override
@RequiresPermission(Manifest.permission.ACCESS_FPS_COUNTER)
public void registerTaskFpsCallback(@IntRange(from = 0) int taskId,
ITaskFpsCallback callback) {
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index 1573d09..90e7bd7 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -1916,7 +1916,6 @@
final int count = tasksToReparent.size();
for (int i = 0; i < count; ++i) {
final Task task = tasksToReparent.get(i);
- final int prevWindowingMode = task.getWindowingMode();
if (syncId >= 0) {
addToSyncSet(syncId, task);
}
@@ -1930,12 +1929,6 @@
hop.getToTop() ? POSITION_TOP : POSITION_BOTTOM,
false /*moveParents*/, "processChildrenTaskReparentHierarchyOp");
}
- // Trim the compatible Recent task (if any) after the Task is reparented and now has
- // a different windowing mode, in order to prevent redundant Recent tasks after
- // reparenting.
- if (prevWindowingMode != task.getWindowingMode()) {
- mService.mTaskSupervisor.mRecentTasks.removeCompatibleRecentTask(task);
- }
}
if (transition != null) transition.collect(newParent);
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index fd1b5be..1c00fbb 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -84,6 +84,7 @@
import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.Watchdog;
+import com.android.server.grammaticalinflection.GrammaticalInflectionManagerInternal;
import com.android.server.wm.ActivityTaskManagerService.HotPath;
import java.io.IOException;
@@ -324,8 +325,6 @@
*/
private volatile int mActivityStateFlags = ACTIVITY_STATE_FLAG_MASK_MIN_TASK_LAYER;
- private final boolean mCanUseSystemGrammaticalGender;
-
public WindowProcessController(@NonNull ActivityTaskManagerService atm,
@NonNull ApplicationInfo info, String name, int uid, int userId, Object owner,
@NonNull WindowProcessListener listener) {
@@ -349,9 +348,6 @@
mUseFifoUiScheduling = com.android.window.flags.Flags.fifoPriorityForMajorUiProcesses()
&& (isSysUiPackage || mAtm.isCallerRecents(uid));
- mCanUseSystemGrammaticalGender = mAtm.mGrammaticalManagerInternal != null
- && mAtm.mGrammaticalManagerInternal.canGetSystemGrammaticalGender(mUid,
- mInfo.packageName);
onConfigurationChanged(atm.getGlobalConfiguration());
mAtm.mPackageConfigPersister.updateConfigIfNeeded(this, mUserId, mInfo.packageName);
}
@@ -1612,11 +1608,6 @@
return;
}
- if (mCanUseSystemGrammaticalGender) {
- config.setGrammaticalGender(
- mAtm.mGrammaticalManagerInternal.getSystemGrammaticalGender(mUserId));
- }
-
if (mPauseConfigurationDispatchCount > 0) {
mHasPendingConfigurationChange = true;
return;
@@ -2139,4 +2130,34 @@
void dumpDebug(ProtoOutputStream proto, long fieldId) {
mListener.dumpDebug(proto, fieldId);
}
+
+ @Override
+ protected boolean setOverrideGender(Configuration requestsTmpConfig, int gender) {
+ return applyConfigGenderOverride(requestsTmpConfig, gender,
+ mAtm.mGrammaticalManagerInternal, mUid);
+ }
+
+ static boolean applyConfigGenderOverride(@NonNull Configuration overrideConfig,
+ @Configuration.GrammaticalGender int override,
+ GrammaticalInflectionManagerInternal service, int uid) {
+ final boolean canGetSystemValue = service != null
+ && service.canGetSystemGrammaticalGender(uid);
+
+ // The priority here is as follows:
+ // - app-specific override if set
+ // - system value if allowed to see it
+ // - global configuration otherwise
+ final int targetValue = (override != Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED)
+ ? override
+ : canGetSystemValue
+ ? Configuration.GRAMMATICAL_GENDER_UNDEFINED
+ : service != null
+ ? service.getGrammaticalGenderFromDeveloperSettings()
+ : Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED;
+ if (overrideConfig.getGrammaticalGenderRaw() == targetValue) {
+ return false;
+ }
+ overrideConfig.setGrammaticalGender(targetValue);
+ return true;
+ }
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index c25080f..e90c845 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -858,6 +858,10 @@
* {@link InsetsStateController#notifyInsetsChanged}.
*/
boolean isReadyToDispatchInsetsState() {
+ if (mStartingData != null) {
+ // Starting window doesn't consider insets.
+ return false;
+ }
final boolean visible = shouldCheckTokenVisibleRequested()
? isVisibleRequested() : isVisible();
return visible && mFrozenInsetsState == null;
diff --git a/services/core/jni/com_android_server_hint_HintManagerService.cpp b/services/core/jni/com_android_server_hint_HintManagerService.cpp
index be18835..2307ace 100644
--- a/services/core/jni/com_android_server_hint_HintManagerService.cpp
+++ b/services/core/jni/com_android_server_hint_HintManagerService.cpp
@@ -34,11 +34,8 @@
#include "jni.h"
-using aidl::android::hardware::power::SessionConfig;
-using aidl::android::hardware::power::SessionHint;
-using aidl::android::hardware::power::SessionMode;
-using aidl::android::hardware::power::SessionTag;
-using aidl::android::hardware::power::WorkDuration;
+namespace hal = aidl::android::hardware::power;
+
using android::power::PowerHintSessionWrapper;
namespace android {
@@ -95,10 +92,11 @@
static jlong createHintSessionWithConfig(JNIEnv* env, int32_t tgid, int32_t uid,
std::vector<int32_t> threadIds, int64_t durationNanos,
- int32_t sessionTag, SessionConfig& config) {
+ int32_t sessionTag, hal::SessionConfig& config) {
auto result =
gPowerHalController.createHintSessionWithConfig(tgid, uid, threadIds, durationNanos,
- static_cast<SessionTag>(sessionTag),
+ static_cast<hal::SessionTag>(
+ sessionTag),
&config);
if (result.isOk()) {
jlong session_ptr = reinterpret_cast<jlong>(result.value().get());
@@ -140,12 +138,12 @@
}
static void reportActualWorkDuration(int64_t session_ptr,
- const std::vector<WorkDuration>& actualDurations) {
+ const std::vector<hal::WorkDuration>& actualDurations) {
auto appSession = reinterpret_cast<PowerHintSessionWrapper*>(session_ptr);
appSession->reportActualWorkDuration(actualDurations);
}
-static void sendHint(int64_t session_ptr, SessionHint hint) {
+static void sendHint(int64_t session_ptr, hal::SessionHint hint) {
auto appSession = reinterpret_cast<PowerHintSessionWrapper*>(session_ptr);
appSession->sendHint(hint);
}
@@ -155,7 +153,7 @@
appSession->setThreads(threadIds);
}
-static void setMode(int64_t session_ptr, SessionMode mode, bool enabled) {
+static void setMode(int64_t session_ptr, hal::SessionMode mode, bool enabled) {
auto appSession = reinterpret_cast<PowerHintSessionWrapper*>(session_ptr);
appSession->setMode(mode, enabled);
}
@@ -189,7 +187,7 @@
return 0;
}
std::vector<int32_t> threadIds(tidArray.get(), tidArray.get() + tidArray.size());
- SessionConfig config;
+ hal::SessionConfig config;
jlong out = createHintSessionWithConfig(env, tgid, uid, std::move(threadIds), durationNanos,
sessionTag, config);
if (out <= 0) {
@@ -223,7 +221,7 @@
ScopedLongArrayRO arrayActualDurations(env, actualDurations);
ScopedLongArrayRO arrayTimeStamps(env, timeStamps);
- std::vector<WorkDuration> actualList(arrayActualDurations.size());
+ std::vector<hal::WorkDuration> actualList(arrayActualDurations.size());
for (size_t i = 0; i < arrayActualDurations.size(); i++) {
actualList[i].timeStampNanos = arrayTimeStamps[i];
actualList[i].durationNanos = arrayActualDurations[i];
@@ -232,7 +230,7 @@
}
static void nativeSendHint(JNIEnv* env, jclass /* clazz */, jlong session_ptr, jint hint) {
- sendHint(session_ptr, static_cast<SessionHint>(hint));
+ sendHint(session_ptr, static_cast<hal::SessionHint>(hint));
}
static void nativeSetThreads(JNIEnv* env, jclass /* clazz */, jlong session_ptr, jintArray tids) {
@@ -244,13 +242,13 @@
static void nativeSetMode(JNIEnv* env, jclass /* clazz */, jlong session_ptr, jint mode,
jboolean enabled) {
- setMode(session_ptr, static_cast<SessionMode>(mode), enabled);
+ setMode(session_ptr, static_cast<hal::SessionMode>(mode), enabled);
}
static void nativeReportActualWorkDuration2(JNIEnv* env, jclass /* clazz */, jlong session_ptr,
jobjectArray jWorkDurations) {
int size = env->GetArrayLength(jWorkDurations);
- std::vector<WorkDuration> workDurations(size);
+ std::vector<hal::WorkDuration> workDurations(size);
for (int i = 0; i < size; i++) {
jobject workDuration = env->GetObjectArrayElement(jWorkDurations, i);
workDurations[i].workPeriodStartTimestampNanos =
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 80bf5b9..fac08eb 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -88,7 +88,6 @@
namespace android {
-static const bool ENABLE_POINTER_CHOREOGRAPHER = input_flags::enable_pointer_choreographer();
static const bool ENABLE_INPUT_FILTER_RUST = input_flags::enable_input_filter_rust_impl();
// The exponent used to calculate the pointer speed scaling factor.
@@ -178,6 +177,7 @@
jfieldID lightTypeInput;
jfieldID lightTypePlayerId;
jfieldID lightTypeKeyboardBacklight;
+ jfieldID lightTypeKeyboardMicMute;
jfieldID lightCapabilityBrightness;
jfieldID lightCapabilityColorRgb;
} gLightClassInfo;
@@ -297,10 +297,8 @@
void setShowTouches(bool enabled);
void setInteractive(bool interactive);
void reloadCalibration();
- void setPointerIconType(PointerIconStyle iconId);
void reloadPointerIcons();
void requestPointerCapture(const sp<IBinder>& windowToken, bool enabled);
- void setCustomPointerIcon(const SpriteIcon& icon);
bool setPointerIcon(std::variant<std::unique_ptr<SpriteIcon>, PointerIconStyle> icon,
int32_t displayId, DeviceId deviceId, int32_t pointerId,
const sp<IBinder>& inputToken);
@@ -315,7 +313,6 @@
/* --- InputReaderPolicyInterface implementation --- */
void getReaderConfiguration(InputReaderConfiguration* outConfig) override;
- std::shared_ptr<PointerControllerInterface> obtainPointerController(int32_t deviceId) override;
void notifyInputDevicesChanged(const std::vector<InputDeviceInfo>& inputDevices) override;
std::shared_ptr<KeyCharacterMap> getKeyboardLayoutOverlay(
const InputDeviceIdentifier& identifier,
@@ -374,7 +371,6 @@
virtual PointerIconStyle getDefaultPointerIconId();
virtual PointerIconStyle getDefaultStylusIconId();
virtual PointerIconStyle getCustomPointerIconId();
- virtual void onPointerDisplayIdChanged(int32_t displayId, const FloatPoint& position);
/* --- PointerChoreographerPolicyInterface implementation --- */
std::shared_ptr<PointerControllerInterface> createPointerController(
@@ -408,19 +404,12 @@
// True if pointer gestures are enabled.
bool pointerGesturesEnabled{true};
- // Show touches feature enable/disable.
- bool showTouches{false};
-
// The latest request to enable or disable Pointer Capture.
PointerCaptureRequest pointerCaptureRequest{};
// Sprite controller singleton, created on first use.
std::shared_ptr<SpriteController> spriteController{};
- // TODO(b/293587049): Remove when the PointerChoreographer refactoring is complete.
- // Pointer controller singleton, created and destroyed as needed.
- std::weak_ptr<PointerController> legacyPointerController{};
-
// The list of PointerControllers created and managed by the PointerChoreographer.
std::list<std::weak_ptr<PointerController>> pointerControllers{};
@@ -503,14 +492,10 @@
dump += StringPrintf(INDENT "Display with Mouse Pointer Acceleration Disabled: %s\n",
dumpSet(mLocked.displaysWithMousePointerAccelerationDisabled).c_str());
dump += StringPrintf(INDENT "Pointer Gestures Enabled: %s\n",
- toString(mLocked.pointerGesturesEnabled));
- dump += StringPrintf(INDENT "Show Touches: %s\n", toString(mLocked.showTouches));
+ toString(mLocked.pointerGesturesEnabled));
dump += StringPrintf(INDENT "Pointer Capture: %s, seq=%" PRIu32 "\n",
mLocked.pointerCaptureRequest.isEnable() ? "Enabled" : "Disabled",
mLocked.pointerCaptureRequest.seq);
- if (auto pc = mLocked.legacyPointerController.lock(); pc) {
- dump += pc->dump();
- }
} // release lock
dump += "\n";
@@ -555,9 +540,7 @@
[&viewports](PointerController& pc) { pc.onDisplayViewportsUpdated(viewports); });
} // release lock
- if (ENABLE_POINTER_CHOREOGRAPHER) {
- mInputManager->getChoreographer().setDisplayViewports(viewports);
- }
+ mInputManager->getChoreographer().setDisplayViewports(viewports);
mInputManager->getReader().requestRefreshConfiguration(
InputReaderConfiguration::Change::DISPLAY_INFO);
}
@@ -699,8 +682,6 @@
: 1;
outConfig->pointerGesturesEnabled = mLocked.pointerGesturesEnabled;
- outConfig->showTouches = mLocked.showTouches;
-
outConfig->pointerCaptureRequest = mLocked.pointerCaptureRequest;
outConfig->setDisplayViewports(mLocked.viewports);
@@ -742,10 +723,6 @@
void NativeInputManager::forEachPointerControllerLocked(
std::function<void(PointerController&)> apply) {
- if (auto pc = mLocked.legacyPointerController.lock(); pc) {
- apply(*pc);
- }
-
auto it = mLocked.pointerControllers.begin();
while (it != mLocked.pointerControllers.end()) {
auto pc = it->lock();
@@ -779,50 +756,16 @@
return android_view_PointerIcon_toNative(env, pointerIconObj.get());
}
-// TODO(b/293587049): Remove the old way of obtaining PointerController when the
-// PointerChoreographer refactoring is complete.
-std::shared_ptr<PointerControllerInterface> NativeInputManager::obtainPointerController(
- int32_t /* deviceId */) {
- ATRACE_CALL();
- std::scoped_lock _l(mLock);
-
- std::shared_ptr<PointerController> controller = mLocked.legacyPointerController.lock();
- if (controller == nullptr) {
- ensureSpriteControllerLocked();
-
- // Disable the functionality of the legacy PointerController if PointerChoreographer is
- // enabled.
- controller = PointerController::create(this, mLooper, *mLocked.spriteController,
- /*enabled=*/!ENABLE_POINTER_CHOREOGRAPHER);
- mLocked.legacyPointerController = controller;
- updateInactivityTimeoutLocked();
- }
-
- return controller;
-}
-
std::shared_ptr<PointerControllerInterface> NativeInputManager::createPointerController(
PointerControllerInterface::ControllerType type) {
std::scoped_lock _l(mLock);
ensureSpriteControllerLocked();
std::shared_ptr<PointerController> pc =
- PointerController::create(this, mLooper, *mLocked.spriteController, /*enabled=*/true,
- type);
+ PointerController::create(this, mLooper, *mLocked.spriteController, type);
mLocked.pointerControllers.emplace_back(pc);
return pc;
}
-void NativeInputManager::onPointerDisplayIdChanged(int32_t pointerDisplayId,
- const FloatPoint& position) {
- if (ENABLE_POINTER_CHOREOGRAPHER) {
- return;
- }
- JNIEnv* env = jniEnv();
- env->CallVoidMethod(mServiceObj, gServiceClassInfo.onPointerDisplayIdChanged, pointerDisplayId,
- position.x, position.y);
- checkAndClearExceptionFromCallback(env, "onPointerDisplayIdChanged");
-}
-
void NativeInputManager::notifyPointerDisplayIdChanged(int32_t pointerDisplayId,
const FloatPoint& position) {
// Notify the Reader so that devices can be reconfigured.
@@ -1209,23 +1152,7 @@
}
void NativeInputManager::setPointerDisplayId(int32_t displayId) {
- if (ENABLE_POINTER_CHOREOGRAPHER) {
- mInputManager->getChoreographer().setDefaultMouseDisplayId(displayId);
- } else {
- { // acquire lock
- std::scoped_lock _l(mLock);
-
- if (mLocked.pointerDisplayId == displayId) {
- return;
- }
-
- ALOGI("Setting pointer display id to %d.", displayId);
- mLocked.pointerDisplayId = displayId;
- } // release lock
-
- mInputManager->getReader().requestRefreshConfiguration(
- InputReaderConfiguration::Change::DISPLAY_INFO);
- }
+ mInputManager->getChoreographer().setDefaultMouseDisplayId(displayId);
}
int32_t NativeInputManager::getMousePointerSpeed() {
@@ -1377,24 +1304,7 @@
}
void NativeInputManager::setShowTouches(bool enabled) {
- if (ENABLE_POINTER_CHOREOGRAPHER) {
- mInputManager->getChoreographer().setShowTouchesEnabled(enabled);
- return;
- }
-
- { // acquire lock
- std::scoped_lock _l(mLock);
-
- if (mLocked.showTouches == enabled) {
- return;
- }
-
- ALOGI("Setting show touches feature to %s.", enabled ? "enabled" : "disabled");
- mLocked.showTouches = enabled;
- } // release lock
-
- mInputManager->getReader().requestRefreshConfiguration(
- InputReaderConfiguration::Change::SHOW_TOUCHES);
+ mInputManager->getChoreographer().setShowTouchesEnabled(enabled);
}
void NativeInputManager::requestPointerCapture(const sp<IBinder>& windowToken, bool enabled) {
@@ -1410,27 +1320,11 @@
InputReaderConfiguration::Change::TOUCH_AFFINE_TRANSFORMATION);
}
-void NativeInputManager::setPointerIconType(PointerIconStyle iconId) {
- std::scoped_lock _l(mLock);
- std::shared_ptr<PointerController> controller = mLocked.legacyPointerController.lock();
- if (controller != nullptr) {
- controller->updatePointerIcon(iconId);
- }
-}
-
void NativeInputManager::reloadPointerIcons() {
std::scoped_lock _l(mLock);
forEachPointerControllerLocked([](PointerController& pc) { pc.reloadPointerResources(); });
}
-void NativeInputManager::setCustomPointerIcon(const SpriteIcon& icon) {
- std::scoped_lock _l(mLock);
- std::shared_ptr<PointerController> controller = mLocked.legacyPointerController.lock();
- if (controller != nullptr) {
- controller->setCustomPointerIcon(icon);
- }
-}
-
bool NativeInputManager::setPointerIcon(
std::variant<std::unique_ptr<SpriteIcon>, PointerIconStyle> icon, int32_t displayId,
DeviceId deviceId, int32_t pointerId, const sp<IBinder>& inputToken) {
@@ -1446,9 +1340,6 @@
}
void NativeInputManager::setPointerIconVisibility(int32_t displayId, bool visible) {
- if (!ENABLE_POINTER_CHOREOGRAPHER) {
- return;
- }
mInputManager->getChoreographer().setPointerIconVisibility(displayId, visible);
}
@@ -1818,36 +1709,12 @@
}
FloatPoint NativeInputManager::getMouseCursorPosition(int32_t displayId) {
- if (ENABLE_POINTER_CHOREOGRAPHER) {
- return mInputManager->getChoreographer().getMouseCursorPosition(displayId);
- }
- // To maintain the status-quo, the displayId parameter (used when PointerChoreographer is
- // enabled) is ignored in the old pipeline.
- std::scoped_lock _l(mLock);
- const auto pc = mLocked.legacyPointerController.lock();
- if (!pc) return {AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION};
-
- return pc->getPosition();
+ return mInputManager->getChoreographer().getMouseCursorPosition(displayId);
}
void NativeInputManager::setStylusPointerIconEnabled(bool enabled) {
- if (ENABLE_POINTER_CHOREOGRAPHER) {
- mInputManager->getChoreographer().setStylusPointerIconEnabled(enabled);
- return;
- }
-
- { // acquire lock
- std::scoped_lock _l(mLock);
-
- if (mLocked.stylusPointerIconEnabled == enabled) {
- return;
- }
-
- mLocked.stylusPointerIconEnabled = enabled;
- } // release lock
-
- mInputManager->getReader().requestRefreshConfiguration(
- InputReaderConfiguration::Change::DISPLAY_INFO);
+ mInputManager->getChoreographer().setStylusPointerIconEnabled(enabled);
+ return;
}
void NativeInputManager::setInputMethodConnectionIsActive(bool isActive) {
@@ -2432,6 +2299,9 @@
} else if (lightInfo.type == InputDeviceLightType::KEYBOARD_BACKLIGHT) {
jTypeId = env->GetStaticIntField(gLightClassInfo.clazz,
gLightClassInfo.lightTypeKeyboardBacklight);
+ } else if (lightInfo.type == InputDeviceLightType::KEYBOARD_MIC_MUTE) {
+ jTypeId = env->GetStaticIntField(gLightClassInfo.clazz,
+ gLightClassInfo.lightTypeKeyboardMicMute);
} else {
ALOGW("Unknown light type %d", lightInfo.type);
continue;
@@ -2594,13 +2464,7 @@
}
static void nativeSetPointerIconType(JNIEnv* env, jobject nativeImplObj, jint iconId) {
- // iconId is set in java from from frameworks/base/core/java/android/view/PointerIcon.java,
- // where the definition in <input/Input.h> is duplicated as a sealed class (type safe enum
- // equivalent in Java).
-
- NativeInputManager* im = getNativeInputManager(env, nativeImplObj);
-
- im->setPointerIconType(static_cast<PointerIconStyle>(iconId));
+ // TODO(b/311416205): Remove
}
static void nativeReloadPointerIcons(JNIEnv* env, jobject nativeImplObj) {
@@ -2610,8 +2474,7 @@
}
static void nativeSetCustomPointerIcon(JNIEnv* env, jobject nativeImplObj, jobject iconObj) {
- NativeInputManager* im = getNativeInputManager(env, nativeImplObj);
- im->setCustomPointerIcon(toSpriteIcon(android_view_PointerIcon_toNative(env, iconObj)));
+ // TODO(b/311416205): Remove
}
static bool nativeSetPointerIcon(JNIEnv* env, jobject nativeImplObj, jobject iconObj,
@@ -3165,6 +3028,8 @@
env->GetStaticFieldID(gLightClassInfo.clazz, "LIGHT_TYPE_PLAYER_ID", "I");
gLightClassInfo.lightTypeKeyboardBacklight =
env->GetStaticFieldID(gLightClassInfo.clazz, "LIGHT_TYPE_KEYBOARD_BACKLIGHT", "I");
+ gLightClassInfo.lightTypeKeyboardMicMute =
+ env->GetStaticFieldID(gLightClassInfo.clazz, "LIGHT_TYPE_KEYBOARD_MIC_MUTE", "I");
gLightClassInfo.lightCapabilityBrightness =
env->GetStaticFieldID(gLightClassInfo.clazz, "LIGHT_CAPABILITY_BRIGHTNESS", "I");
gLightClassInfo.lightCapabilityColorRgb =
diff --git a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
index 6ef1436..0c83e8e 100644
--- a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
+++ b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
@@ -66,6 +66,7 @@
import android.util.Slog;
import android.util.SparseArray;
+import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.server.credentials.metrics.ApiName;
import com.android.server.credentials.metrics.ApiStatus;
@@ -1166,11 +1167,17 @@
settingsWrapper.getStringForUser(
Settings.Secure.AUTOFILL_SERVICE, UserHandle.myUserId());
- // If there is an autofill provider and it is the placeholder indicating
+ // If there is an autofill provider and it is the credential autofill service indicating
// that the currently selected primary provider does not support autofill
- // then we should wipe the setting to keep it in sync.
- if (autofillProvider != null && primaryProviders.isEmpty()) {
- if (autofillProvider.equals(AUTOFILL_PLACEHOLDER_VALUE)) {
+ // then we should keep as is
+ String credentialAutofillService = settingsWrapper.mContext.getResources().getString(
+ R.string.config_defaultCredentialManagerAutofillService);
+ if (autofillProvider != null && primaryProviders.isEmpty() && !TextUtils.equals(
+ autofillProvider, credentialAutofillService)) {
+ // If the existing autofill provider is from the app being removed
+ // then erase the autofill service setting.
+ ComponentName cn = ComponentName.unflattenFromString(autofillProvider);
+ if (cn != null && cn.getPackageName().equals(packageName)) {
if (!settingsWrapper.putStringForUser(
Settings.Secure.AUTOFILL_SERVICE,
"",
@@ -1178,19 +1185,6 @@
/* overrideableByRestore= */ true)) {
Slog.e(TAG, "Failed to remove autofill package: " + packageName);
}
- } else {
- // If the existing autofill provider is from the app being removed
- // then erase the autofill service setting.
- ComponentName cn = ComponentName.unflattenFromString(autofillProvider);
- if (cn != null && cn.getPackageName().equals(packageName)) {
- if (!settingsWrapper.putStringForUser(
- Settings.Secure.AUTOFILL_SERVICE,
- "",
- UserHandle.myUserId(),
- /* overrideableByRestore= */ true)) {
- Slog.e(TAG, "Failed to remove autofill package: " + packageName);
- }
- }
}
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/BooleanPolicySerializer.java b/services/devicepolicy/java/com/android/server/devicepolicy/BooleanPolicySerializer.java
index 950ec77..502607b 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/BooleanPolicySerializer.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/BooleanPolicySerializer.java
@@ -19,7 +19,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.admin.BooleanPolicyValue;
-import android.app.admin.PolicyKey;
import android.util.Log;
import com.android.modules.utils.TypedXmlPullParser;
@@ -37,8 +36,7 @@
private static final String TAG = "BooleanPolicySerializer";
@Override
- void saveToXml(PolicyKey policyKey, TypedXmlSerializer serializer, @NonNull Boolean value)
- throws IOException {
+ void saveToXml(TypedXmlSerializer serializer, @NonNull Boolean value) throws IOException {
Objects.requireNonNull(value);
serializer.attributeBoolean(/* namespace= */ null, ATTR_VALUE, value);
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/BundlePolicySerializer.java b/services/devicepolicy/java/com/android/server/devicepolicy/BundlePolicySerializer.java
index d24afabe..a65c7e1 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/BundlePolicySerializer.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/BundlePolicySerializer.java
@@ -18,8 +18,6 @@
import android.annotation.NonNull;
import android.app.admin.BundlePolicyValue;
-import android.app.admin.PackagePolicyKey;
-import android.app.admin.PolicyKey;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.Log;
@@ -53,14 +51,8 @@
private static final String ATTR_TYPE_BUNDLE_ARRAY = "BA";
@Override
- void saveToXml(@NonNull PolicyKey policyKey, TypedXmlSerializer serializer,
- @NonNull Bundle value) throws IOException {
+ void saveToXml(TypedXmlSerializer serializer, @NonNull Bundle value) throws IOException {
Objects.requireNonNull(value);
- Objects.requireNonNull(policyKey);
- if (!(policyKey instanceof PackagePolicyKey)) {
- throw new IllegalArgumentException("policyKey is not of type "
- + "PackagePolicyKey");
- }
writeBundle(value, serializer);
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/ComponentNamePolicySerializer.java b/services/devicepolicy/java/com/android/server/devicepolicy/ComponentNamePolicySerializer.java
index 6303a1a..01f56e0 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/ComponentNamePolicySerializer.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/ComponentNamePolicySerializer.java
@@ -19,7 +19,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.admin.ComponentNamePolicyValue;
-import android.app.admin.PolicyKey;
import android.content.ComponentName;
import android.util.Log;
@@ -37,8 +36,7 @@
private static final String ATTR_CLASS_NAME = "class-name";
@Override
- void saveToXml(PolicyKey policyKey, TypedXmlSerializer serializer,
- @NonNull ComponentName value) throws IOException {
+ void saveToXml(TypedXmlSerializer serializer, @NonNull ComponentName value) throws IOException {
Objects.requireNonNull(value);
serializer.attribute(
/* namespace= */ null, ATTR_PACKAGE_NAME, value.getPackageName());
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 85ab562..375fc5a 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -349,8 +349,8 @@
import android.app.admin.PreferentialNetworkServiceConfig;
import android.app.admin.SecurityLog;
import android.app.admin.SecurityLog.SecurityEvent;
+import android.app.admin.PackageSetPolicyValue;
import android.app.admin.StartInstallingUpdateCallback;
-import android.app.admin.StringSetPolicyValue;
import android.app.admin.SystemUpdateInfo;
import android.app.admin.SystemUpdatePolicy;
import android.app.admin.UnsafeStateException;
@@ -455,10 +455,10 @@
import android.security.IKeyChainService;
import android.security.KeyChain;
import android.security.KeyChain.KeyChainConnection;
-import android.security.KeyStore;
import android.security.keymaster.KeymasterCertificateChain;
import android.security.keystore.AttestationUtils;
import android.security.keystore.KeyGenParameterSpec;
+import android.security.keystore.KeyProperties;
import android.security.keystore.ParcelableKeyGenParameterSpec;
import android.stats.devicepolicy.DevicePolicyEnums;
import android.telecom.TelecomManager;
@@ -1985,11 +1985,6 @@
CryptoTestHelper.runAndLogSelfTest();
}
- public String[] getPersonalAppsForSuspension(@UserIdInt int userId) {
- return PersonalAppsSuspensionHelper.forUser(mContext, userId)
- .getPersonalAppsForSuspension();
- }
-
public long systemCurrentTimeMillis() {
return System.currentTimeMillis();
}
@@ -6248,7 +6243,7 @@
try (KeyChainConnection keyChainConnection =
KeyChain.bindAsUser(mContext, caller.getUserHandle())) {
IKeyChainService keyChain = keyChainConnection.getService();
- if (!keyChain.installKeyPair(privKey, cert, chain, alias, KeyStore.UID_SELF)) {
+ if (!keyChain.installKeyPair(privKey, cert, chain, alias, KeyProperties.UID_SELF)) {
logInstallKeyPairFailure(caller, isCredentialManagementApp);
return false;
}
@@ -6583,7 +6578,7 @@
}
// As the caller will be granted access to the key, ensure no UID was specified, as
// it will not have the desired effect.
- if (keySpec.getUid() != KeyStore.UID_SELF) {
+ if (keySpec.getUid() != KeyProperties.UID_SELF) {
Slogf.e(LOG_TAG, "Only the caller can be granted access to the generated keypair.");
logGenerateKeyPairFailure(caller, isCredentialManagementApp);
return false;
@@ -12078,7 +12073,7 @@
mDevicePolicyEngine.setLocalPolicy(
PolicyDefinition.PERMITTED_INPUT_METHODS,
admin,
- new StringSetPolicyValue(new HashSet<>(packageList)),
+ new PackageSetPolicyValue(new HashSet<>(packageList)),
userId);
}
}
@@ -20363,12 +20358,12 @@
mDevicePolicyEngine.setGlobalPolicy(
PolicyDefinition.USER_CONTROLLED_DISABLED_PACKAGES,
enforcingAdmin,
- new StringSetPolicyValue(packages));
+ new PackageSetPolicyValue(packages));
} else {
mDevicePolicyEngine.setLocalPolicy(
PolicyDefinition.USER_CONTROLLED_DISABLED_PACKAGES,
enforcingAdmin,
- new StringSetPolicyValue(packages),
+ new PackageSetPolicyValue(packages),
caller.getUserId());
}
}
@@ -21610,9 +21605,12 @@
== HEADLESS_DEVICE_OWNER_MODE_SINGLE_USER;
}
- if (Flags.headlessSingleUserFixes() && mInjector.userManagerIsHeadlessSystemUserMode()
- && isSingleUserMode && !mInjector.isChangeEnabled(
- PROVISION_SINGLE_USER_MODE, deviceAdmin.getPackageName(), caller.getUserId())) {
+ if (Flags.headlessSingleMinTargetSdk()
+ && mInjector.userManagerIsHeadlessSystemUserMode()
+ && isSingleUserMode
+ && !mInjector.isChangeEnabled(
+ PROVISION_SINGLE_USER_MODE, deviceAdmin.getPackageName(),
+ caller.getUserId())) {
throw new IllegalStateException("Device admin is not targeting Android V.");
}
@@ -24047,7 +24045,7 @@
mDevicePolicyEngine.setLocalPolicy(
PolicyDefinition.PERMITTED_INPUT_METHODS,
enforcingAdmin,
- new StringSetPolicyValue(
+ new PackageSetPolicyValue(
new HashSet<>(admin.permittedInputMethods)),
admin.getUserHandle().getIdentifier());
}
@@ -24056,7 +24054,7 @@
mDevicePolicyEngine.setLocalPolicy(
PolicyDefinition.PERMITTED_INPUT_METHODS,
enforcingAdmin,
- new StringSetPolicyValue(
+ new PackageSetPolicyValue(
new HashSet<>(admin.getParentActiveAdmin()
.permittedInputMethods)),
getProfileParentId(admin.getUserHandle().getIdentifier()));
@@ -24112,12 +24110,14 @@
mDevicePolicyEngine.setGlobalPolicy(
PolicyDefinition.USER_CONTROLLED_DISABLED_PACKAGES,
enforcingAdmin,
- new StringSetPolicyValue(new HashSet<>(admin.protectedPackages)));
+ new PackageSetPolicyValue(
+ new HashSet<>(admin.protectedPackages)));
} else {
mDevicePolicyEngine.setLocalPolicy(
PolicyDefinition.USER_CONTROLLED_DISABLED_PACKAGES,
enforcingAdmin,
- new StringSetPolicyValue(new HashSet<>(admin.protectedPackages)),
+ new PackageSetPolicyValue(
+ new HashSet<>(admin.protectedPackages)),
admin.getUserHandle().getIdentifier());
}
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/IntegerPolicySerializer.java b/services/devicepolicy/java/com/android/server/devicepolicy/IntegerPolicySerializer.java
index 45a2d2a..ebbf22c 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/IntegerPolicySerializer.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/IntegerPolicySerializer.java
@@ -19,7 +19,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.admin.IntegerPolicyValue;
-import android.app.admin.PolicyKey;
import android.util.Log;
import com.android.modules.utils.TypedXmlPullParser;
@@ -37,8 +36,7 @@
private static final String ATTR_VALUE = "value";
@Override
- void saveToXml(PolicyKey policyKey, TypedXmlSerializer serializer,
- @NonNull Integer value) throws IOException {
+ void saveToXml(TypedXmlSerializer serializer, @NonNull Integer value) throws IOException {
Objects.requireNonNull(value);
serializer.attributeInt(/* namespace= */ null, ATTR_VALUE, value);
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/LockTaskPolicySerializer.java b/services/devicepolicy/java/com/android/server/devicepolicy/LockTaskPolicySerializer.java
index 20bd2d7..13412d0 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/LockTaskPolicySerializer.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/LockTaskPolicySerializer.java
@@ -18,7 +18,6 @@
import android.annotation.NonNull;
import android.app.admin.LockTaskPolicy;
-import android.app.admin.PolicyKey;
import android.util.Log;
import com.android.modules.utils.TypedXmlPullParser;
@@ -39,8 +38,8 @@
private static final String ATTR_FLAGS = "flags";
@Override
- void saveToXml(PolicyKey policyKey, TypedXmlSerializer serializer,
- @NonNull LockTaskPolicy value) throws IOException {
+ void saveToXml(TypedXmlSerializer serializer, @NonNull LockTaskPolicy value)
+ throws IOException {
Objects.requireNonNull(value);
serializer.attribute(
/* namespace= */ null,
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/LongPolicySerializer.java b/services/devicepolicy/java/com/android/server/devicepolicy/LongPolicySerializer.java
index 522c4b5..c363e66 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/LongPolicySerializer.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/LongPolicySerializer.java
@@ -19,7 +19,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.admin.LongPolicyValue;
-import android.app.admin.PolicyKey;
import android.util.Log;
import com.android.modules.utils.TypedXmlPullParser;
@@ -37,8 +36,7 @@
private static final String ATTR_VALUE = "value";
@Override
- void saveToXml(PolicyKey policyKey, TypedXmlSerializer serializer,
- @NonNull Long value) throws IOException {
+ void saveToXml(TypedXmlSerializer serializer, @NonNull Long value) throws IOException {
Objects.requireNonNull(value);
serializer.attributeLong(/* namespace= */ null, ATTR_VALUE, value);
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/StringSetPolicySerializer.java b/services/devicepolicy/java/com/android/server/devicepolicy/PackageSetPolicySerializer.java
similarity index 79%
rename from services/devicepolicy/java/com/android/server/devicepolicy/StringSetPolicySerializer.java
rename to services/devicepolicy/java/com/android/server/devicepolicy/PackageSetPolicySerializer.java
index 0265453..c4da029 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/StringSetPolicySerializer.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/PackageSetPolicySerializer.java
@@ -18,9 +18,8 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.app.admin.PolicyKey;
import android.app.admin.PolicyValue;
-import android.app.admin.StringSetPolicyValue;
+import android.app.admin.PackageSetPolicyValue;
import android.util.Log;
import com.android.modules.utils.TypedXmlPullParser;
@@ -31,12 +30,11 @@
import java.util.Set;
// TODO(scottjonathan): Replace with generic set implementation
-final class StringSetPolicySerializer extends PolicySerializer<Set<String>> {
+final class PackageSetPolicySerializer extends PolicySerializer<Set<String>> {
private static final String ATTR_VALUES = "strings";
private static final String ATTR_VALUES_SEPARATOR = ";";
@Override
- void saveToXml(PolicyKey policyKey, TypedXmlSerializer serializer,
- @NonNull Set<String> value) throws IOException {
+ void saveToXml(TypedXmlSerializer serializer, @NonNull Set<String> value) throws IOException {
Objects.requireNonNull(value);
serializer.attribute(
/* namespace= */ null, ATTR_VALUES, String.join(ATTR_VALUES_SEPARATOR, value));
@@ -47,10 +45,10 @@
PolicyValue<Set<String>> readFromXml(TypedXmlPullParser parser) {
String valuesStr = parser.getAttributeValue(/* namespace= */ null, ATTR_VALUES);
if (valuesStr == null) {
- Log.e(DevicePolicyEngine.TAG, "Error parsing StringSet policy value.");
+ Log.e(DevicePolicyEngine.TAG, "Error parsing PackageSet policy value.");
return null;
}
Set<String> values = Set.of(valuesStr.split(ATTR_VALUES_SEPARATOR));
- return new StringSetPolicyValue(values);
+ return new PackageSetPolicyValue(values);
}
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/StringSetUnion.java b/services/devicepolicy/java/com/android/server/devicepolicy/PackageSetUnion.java
similarity index 79%
rename from services/devicepolicy/java/com/android/server/devicepolicy/StringSetUnion.java
rename to services/devicepolicy/java/com/android/server/devicepolicy/PackageSetUnion.java
index 5298960..d1e241b 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/StringSetUnion.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/PackageSetUnion.java
@@ -18,14 +18,15 @@
import android.annotation.NonNull;
import android.app.admin.PolicyValue;
-import android.app.admin.StringSetPolicyValue;
+import android.app.admin.PackageSetPolicyValue;
+import android.app.admin.StringSetUnion;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Objects;
import java.util.Set;
-final class StringSetUnion extends ResolutionMechanism<Set<String>> {
+final class PackageSetUnion extends ResolutionMechanism<Set<String>> {
@Override
PolicyValue<Set<String>> resolve(
@@ -38,17 +39,17 @@
for (PolicyValue<Set<String>> policy : adminPolicies.values()) {
unionOfPolicies.addAll(policy.getValue());
}
- return new StringSetPolicyValue(unionOfPolicies);
+ return new PackageSetPolicyValue(unionOfPolicies);
}
@Override
- android.app.admin.StringSetUnion getParcelableResolutionMechanism() {
- return new android.app.admin.StringSetUnion();
+ StringSetUnion getParcelableResolutionMechanism() {
+ return new StringSetUnion();
}
@Override
public String toString() {
- return "SetUnion {}";
+ return "PackageSetUnion {}";
}
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/PersonalAppsSuspensionHelper.java b/services/devicepolicy/java/com/android/server/devicepolicy/PersonalAppsSuspensionHelper.java
index 8cb511e..7483b43 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/PersonalAppsSuspensionHelper.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/PersonalAppsSuspensionHelper.java
@@ -37,7 +37,6 @@
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.IndentingPrintWriter;
-import android.util.Log;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.IAccessibilityManager;
import android.view.inputmethod.InputMethodInfo;
@@ -107,10 +106,6 @@
for (final String pkg : unsuspendablePackages) {
result.remove(pkg);
}
-
- if (Log.isLoggable(LOG_TAG, Log.INFO)) {
- Slogf.i(LOG_TAG, "Packages subject to suspension: %s", String.join(",", result));
- }
return result.toArray(new String[0]);
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java
index 7a9fa0f..8d980b5 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java
@@ -162,9 +162,9 @@
new PolicyDefinition<>(
new NoArgsPolicyKey(
DevicePolicyIdentifiers.USER_CONTROL_DISABLED_PACKAGES_POLICY),
- new StringSetUnion(),
+ new PackageSetUnion(),
PolicyEnforcerCallbacks::setUserControlDisabledPackages,
- new StringSetPolicySerializer());
+ new PackageSetPolicySerializer());
// This is saved in the static map sPolicyDefinitions so that we're able to reconstruct the
// actual policy with the correct arguments (i.e. packageName) when reading the policies from
@@ -328,7 +328,7 @@
new MostRecent<>(),
POLICY_FLAG_LOCAL_ONLY_POLICY | POLICY_FLAG_INHERITABLE,
(Set<String> value, Context context, Integer userId, PolicyKey policyKey) -> true,
- new StringSetPolicySerializer());
+ new PackageSetPolicySerializer());
static PolicyDefinition<Boolean> SCREEN_CAPTURE_DISABLED = new PolicyDefinition<>(
@@ -684,7 +684,7 @@
void savePolicyValueToXml(TypedXmlSerializer serializer, V value)
throws IOException {
- mPolicySerializer.saveToXml(mPolicyKey, serializer, value);
+ mPolicySerializer.saveToXml(serializer, value);
}
@Nullable
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyEnforcerCallbacks.java b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyEnforcerCallbacks.java
index eeb4976..4bf3ff4 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyEnforcerCallbacks.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyEnforcerCallbacks.java
@@ -375,6 +375,7 @@
private static void suspendPersonalAppsInPackageManager(Context context, int userId) {
final String[] appsToSuspend = PersonalAppsSuspensionHelper.forUser(context, userId)
.getPersonalAppsForSuspension();
+ Slogf.i(LOG_TAG, "Suspending personal apps: %s", String.join(",", appsToSuspend));
final String[] failedApps = LocalServices.getService(PackageManagerInternal.class)
.setPackagesSuspendedByAdmin(userId, appsToSuspend, true);
if (!ArrayUtils.isEmpty(failedApps)) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/PolicySerializer.java b/services/devicepolicy/java/com/android/server/devicepolicy/PolicySerializer.java
index 5af2fa2..e83b031 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/PolicySerializer.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/PolicySerializer.java
@@ -17,7 +17,6 @@
package com.android.server.devicepolicy;
import android.annotation.NonNull;
-import android.app.admin.PolicyKey;
import android.app.admin.PolicyValue;
import com.android.modules.utils.TypedXmlPullParser;
@@ -26,7 +25,6 @@
import java.io.IOException;
abstract class PolicySerializer<V> {
- abstract void saveToXml(PolicyKey policyKey, TypedXmlSerializer serializer, @NonNull V value)
- throws IOException;
+ abstract void saveToXml(TypedXmlSerializer serializer, @NonNull V value) throws IOException;
abstract PolicyValue<V> readFromXml(TypedXmlPullParser parser);
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 8caf5ae..8755a80 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -1618,7 +1618,8 @@
wm = WindowManagerService.main(context, inputManager, !mFirstBoot,
new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);
ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
- DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);
+ DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_HIGH
+ | DUMP_FLAG_PROTO);
ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
/* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
t.traceEnd();
diff --git a/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt b/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt
index 87af841..9e4f821 100644
--- a/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt
+++ b/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt
@@ -63,11 +63,8 @@
private val privilegedPermissionAllowlistViolations = MutableIndexedSet<String>()
- /**
- * Test-only switch to enforce signature permission allowlist even on debuggable builds.
- */
- @Volatile
- var isSignaturePermissionAllowlistForceEnforced = false
+ /** Test-only switch to enforce signature permission allowlist even on debuggable builds. */
+ @Volatile var isSignaturePermissionAllowlistForceEnforced = false
override val subjectScheme: String
get() = UidUri.SCHEME
@@ -108,8 +105,8 @@
val changedPermissionNames = MutableIndexedSet<String>()
packageNames.forEachIndexed { _, packageName ->
// The package may still be removed even if it was once notified as installed.
- val packageState = newState.externalState.packageStates[packageName]
- ?: return@forEachIndexed
+ val packageState =
+ newState.externalState.packageStates[packageName] ?: return@forEachIndexed
adoptPermissions(packageState, changedPermissionNames)
addPermissionGroups(packageState)
addPermissions(packageState, changedPermissionNames)
@@ -122,14 +119,14 @@
}
packageNames.forEachIndexed { _, packageName ->
- val packageState = newState.externalState.packageStates[packageName]
- ?: return@forEachIndexed
+ val packageState =
+ newState.externalState.packageStates[packageName] ?: return@forEachIndexed
val installedPackageState = if (isSystemUpdated) packageState else null
evaluateAllPermissionStatesForPackage(packageState, installedPackageState)
}
packageNames.forEachIndexed { _, packageName ->
- val packageState = newState.externalState.packageStates[packageName]
- ?: return@forEachIndexed
+ val packageState =
+ newState.externalState.packageStates[packageName] ?: return@forEachIndexed
newState.externalState.userIds.forEachIndexed { _, userId ->
inheritImplicitPermissionStates(packageState.appId, userId)
}
@@ -1775,6 +1772,7 @@
Manifest.permission.READ_MEDIA_AUDIO,
Manifest.permission.READ_MEDIA_IMAGES,
Manifest.permission.READ_MEDIA_VIDEO,
+ Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED,
)
private val NEARBY_DEVICES_PERMISSIONS =
diff --git a/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt b/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt
index 65feeb0..b155829 100644
--- a/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt
+++ b/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt
@@ -2027,7 +2027,7 @@
val writer = IndentingPrintWriter(pw, " ")
- if (args.isNullOrEmpty()) {
+ if (args.isNullOrEmpty() || args[0] == "-a") {
service.getState {
writer.dumpSystemState(state)
getAllAppIdPackageNames(state).forEachIndexed { _, appId, packageNames ->
diff --git a/services/print/java/com/android/server/print/PrintManagerService.java b/services/print/java/com/android/server/print/PrintManagerService.java
index 4a8d73d2..07cda37 100644
--- a/services/print/java/com/android/server/print/PrintManagerService.java
+++ b/services/print/java/com/android/server/print/PrintManagerService.java
@@ -875,7 +875,7 @@
}
private void registerBroadcastReceivers() {
- PackageMonitor monitor = new PackageMonitor() {
+ PackageMonitor monitor = new PackageMonitor(true) {
/**
* Checks if the package contains a print service.
*
diff --git a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
index 68038fa..622e702 100644
--- a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
+++ b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
@@ -243,6 +243,7 @@
return;
}
sSelfService.mIProfcollect.process();
+ jobFinished(params, false);
} catch (RemoteException e) {
Log.e(LOG_TAG, "Failed to process profiles in background: "
+ e.getMessage());
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodBindingControllerTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodBindingControllerTest.java
index 1f0a375..70903cb 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodBindingControllerTest.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodBindingControllerTest.java
@@ -77,9 +77,13 @@
mCountDownLatch = new CountDownLatch(1);
// Remove flag Context.BIND_SCHEDULE_LIKE_TOP_APP because in tests we are not calling
// from system.
- mBindingController =
- new InputMethodBindingController(
- mInputMethodManagerService, mImeConnectionBindFlags, mCountDownLatch);
+ synchronized (ImfLock.class) {
+ mBindingController =
+ new InputMethodBindingController(
+ mInputMethodManagerService.getCurrentImeUserIdLocked(),
+ mInputMethodManagerService, mImeConnectionBindFlags,
+ mCountDownLatch);
+ }
}
@Test
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java
index b4cf799..cff2265 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java
@@ -222,7 +222,7 @@
Process.THREAD_PRIORITY_FOREGROUND, /* allowIo */
false);
mInputMethodManagerService = new InputMethodManagerService(mContext, mServiceThread,
- mMockInputMethodBindingController);
+ unusedUserId -> mMockInputMethodBindingController);
spyOn(mInputMethodManagerService);
// Start a InputMethodManagerService.Lifecycle to publish and manage the lifecycle of
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/UserDataRepositoryTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/UserDataRepositoryTest.java
index a15b170..c3a87da 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/UserDataRepositoryTest.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/UserDataRepositoryTest.java
@@ -18,6 +18,7 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -38,6 +39,7 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.function.IntFunction;
// This test is designed to run on both device and host (Ravenwood) side.
public final class UserDataRepositoryTest {
@@ -51,19 +53,34 @@
@Mock
private UserManagerInternal mMockUserManagerInternal;
+ @Mock
+ private InputMethodManagerService mMockInputMethodManagerService;
+
private Handler mHandler;
+ private IntFunction<InputMethodBindingController> mBindingControllerFactory;
+
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mHandler = new Handler(Looper.getMainLooper());
+ mBindingControllerFactory = new IntFunction<InputMethodBindingController>() {
+
+ @Override
+ public InputMethodBindingController apply(int userId) {
+ return new InputMethodBindingController(userId, mMockInputMethodManagerService);
+ }
+ };
}
@Test
public void testUserDataRepository_addsNewUserInfoOnUserCreatedEvent() {
// Create UserDataRepository and capture the user lifecycle listener
final var captor = ArgumentCaptor.forClass(UserManagerInternal.UserLifecycleListener.class);
- final var repository = new UserDataRepository(mHandler, mMockUserManagerInternal);
+ final var bindingControllerFactorySpy = spy(mBindingControllerFactory);
+ final var repository = new UserDataRepository(mHandler, mMockUserManagerInternal,
+ bindingControllerFactorySpy);
+
verify(mMockUserManagerInternal, times(1)).addUserLifecycleListener(captor.capture());
final var listener = captor.getValue();
@@ -77,14 +94,20 @@
// Assert UserDataRepository contains the expected UserData
final var allUserData = collectUserData(repository);
assertThat(allUserData).hasSize(1);
- assertThat(allUserData.get(0).mUserId).isEqualTo(userInfo.id);
+ assertThat(allUserData.get(0).mUserId).isEqualTo(ANY_USER_ID);
+
+ // Assert UserDataRepository called the InputMethodBindingController creator function.
+ verify(bindingControllerFactorySpy).apply(ANY_USER_ID);
+ assertThat(allUserData.get(0).mBindingController.mUserId).isEqualTo(ANY_USER_ID);
}
@Test
public void testUserDataRepository_removesUserInfoOnUserRemovedEvent() {
// Create UserDataRepository and capture the user lifecycle listener
final var captor = ArgumentCaptor.forClass(UserManagerInternal.UserLifecycleListener.class);
- final var repository = new UserDataRepository(mHandler, mMockUserManagerInternal);
+ final var repository = new UserDataRepository(mHandler, mMockUserManagerInternal,
+ userId -> new InputMethodBindingController(userId, mMockInputMethodManagerService));
+
verify(mMockUserManagerInternal, times(1)).addUserLifecycleListener(captor.capture());
final var listener = captor.getValue();
@@ -104,7 +127,8 @@
@Test
public void testGetOrCreate() {
- final var repository = new UserDataRepository(mHandler, mMockUserManagerInternal);
+ final var repository = new UserDataRepository(mHandler, mMockUserManagerInternal,
+ mBindingControllerFactory);
synchronized (ImfLock.class) {
final var userData = repository.getOrCreate(ANY_USER_ID);
@@ -114,6 +138,9 @@
final var allUserData = collectUserData(repository);
assertThat(allUserData).hasSize(1);
assertThat(allUserData.get(0).mUserId).isEqualTo(ANY_USER_ID);
+
+ // Assert UserDataRepository called the InputMethodBindingController creator function.
+ assertThat(allUserData.get(0).mBindingController.mUserId).isEqualTo(ANY_USER_ID);
}
private List<UserDataRepository.UserData> collectUserData(UserDataRepository repository) {
diff --git a/services/tests/displayservicetests/src/com/android/server/display/AutomaticBrightnessControllerTest.java b/services/tests/displayservicetests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
index 64253e1..3628a57 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
@@ -1030,7 +1030,7 @@
}
@Test
- public void testBrightnessBasedOnLastObservedLux() throws Exception {
+ public void testBrightnessBasedOnLastUsedLux() throws Exception {
ArgumentCaptor<SensorEventListener> listenerCaptor =
ArgumentCaptor.forClass(SensorEventListener.class);
verify(mSensorManager).registerListener(listenerCaptor.capture(), eq(mLightSensor),
@@ -1054,7 +1054,7 @@
/* userChanged= */ false, DisplayPowerRequest.POLICY_BRIGHT, Display.STATE_ON,
/* shouldResetShortTermModel= */ true);
assertEquals(normalizedBrightness,
- mController.getAutomaticScreenBrightnessBasedOnLastObservedLux(
+ mController.getAutomaticScreenBrightnessBasedOnLastUsedLux(
/* brightnessEvent= */ null), EPSILON);
}
@@ -1090,7 +1090,7 @@
mController.getAutomaticScreenBrightness(
/* brightnessEvent= */ null), EPSILON);
assertEquals(normalizedBrightness * DOZE_SCALE_FACTOR,
- mController.getAutomaticScreenBrightnessBasedOnLastObservedLux(
+ mController.getAutomaticScreenBrightnessBasedOnLastUsedLux(
/* brightnessEvent= */ null), EPSILON);
}
@@ -1128,7 +1128,7 @@
assertEquals(normalizedBrightness,
mController.getAutomaticScreenBrightness(/* brightnessEvent= */ null), EPSILON);
assertEquals(normalizedBrightness,
- mController.getAutomaticScreenBrightnessBasedOnLastObservedLux(
+ mController.getAutomaticScreenBrightnessBasedOnLastUsedLux(
/* brightnessEvent= */ null), EPSILON);
}
@@ -1163,7 +1163,7 @@
assertEquals(normalizedBrightness,
mController.getAutomaticScreenBrightness(/* brightnessEvent= */ null), EPSILON);
assertEquals(normalizedBrightness,
- mController.getAutomaticScreenBrightnessBasedOnLastObservedLux(
+ mController.getAutomaticScreenBrightnessBasedOnLastUsedLux(
/* brightnessEvent= */ null), EPSILON);
}
}
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java
index 78ebdb1..80f38eb 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java
@@ -1776,7 +1776,7 @@
float brightness = 0.277f;
when(mHolder.displayPowerState.getColorFadeLevel()).thenReturn(1.0f);
when(mHolder.automaticBrightnessController
- .getAutomaticScreenBrightnessBasedOnLastObservedLux(any(BrightnessEvent.class)))
+ .getAutomaticScreenBrightnessBasedOnLastUsedLux(any(BrightnessEvent.class)))
.thenReturn(brightness);
when(mHolder.hbmController.getCurrentBrightnessMax())
.thenReturn(PowerManager.BRIGHTNESS_MAX);
@@ -1840,7 +1840,7 @@
float brightness = 0.277f;
when(mHolder.displayPowerState.getColorFadeLevel()).thenReturn(1.0f);
when(mHolder.automaticBrightnessController
- .getAutomaticScreenBrightnessBasedOnLastObservedLux(any(BrightnessEvent.class)))
+ .getAutomaticScreenBrightnessBasedOnLastUsedLux(any(BrightnessEvent.class)))
.thenReturn(brightness);
when(mHolder.hbmController.getCurrentBrightnessMax())
.thenReturn(PowerManager.BRIGHTNESS_MAX);
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/DisplayBrightnessControllerTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/DisplayBrightnessControllerTest.java
index 13a1445..c5105e7 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/brightness/DisplayBrightnessControllerTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/DisplayBrightnessControllerTest.java
@@ -32,7 +32,9 @@
import android.content.Context;
import android.content.res.Resources;
+import android.hardware.SensorManager;
import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
+import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.PowerManager;
import android.view.Display;
@@ -41,7 +43,11 @@
import androidx.test.runner.AndroidJUnit4;
import com.android.server.display.AutomaticBrightnessController;
+import com.android.server.display.BrightnessMappingStrategy;
import com.android.server.display.BrightnessSetting;
+import com.android.server.display.DisplayDeviceConfig;
+import com.android.server.display.brightness.strategy.AutoBrightnessFallbackStrategy;
+import com.android.server.display.brightness.strategy.AutomaticBrightnessStrategy;
import com.android.server.display.brightness.strategy.DisplayBrightnessStrategy;
import com.android.server.display.brightness.strategy.OffloadBrightnessStrategy;
import com.android.server.display.brightness.strategy.TemporaryBrightnessStrategy;
@@ -75,14 +81,14 @@
@Mock
private HandlerExecutor mBrightnessChangeExecutor;
- private final DisplayBrightnessController.Injector mInjector = new
- DisplayBrightnessController.Injector() {
- @Override
- DisplayBrightnessStrategySelector getDisplayBrightnessStrategySelector(
- Context context, int displayId, DisplayManagerFlags flags) {
- return mDisplayBrightnessStrategySelector;
- }
- };
+ private final DisplayBrightnessController.Injector mInjector =
+ new DisplayBrightnessController.Injector() {
+ @Override
+ DisplayBrightnessStrategySelector getDisplayBrightnessStrategySelector(
+ Context context, int displayId, DisplayManagerFlags flags) {
+ return mDisplayBrightnessStrategySelector;
+ }
+ };
private DisplayBrightnessController mDisplayBrightnessController;
@@ -196,10 +202,9 @@
pendingScreenBrightness, /* delta= */ 0.0f);
assertEquals(mDisplayBrightnessController.getLastUserSetScreenBrightness(),
pendingScreenBrightness, /* delta= */ 0.0f);
- verify(mBrightnessChangeExecutor, times(2))
- .execute(mOnBrightnessChangeRunnable);
- verify(temporaryBrightnessStrategy, times(2))
- .setTemporaryScreenBrightness(PowerManager.BRIGHTNESS_INVALID_FLOAT);
+ verify(mBrightnessChangeExecutor, times(2)).execute(mOnBrightnessChangeRunnable);
+ verify(temporaryBrightnessStrategy, times(2)).setTemporaryScreenBrightness(
+ PowerManager.BRIGHTNESS_INVALID_FLOAT);
assertEquals(mDisplayBrightnessController.getPendingScreenBrightness(),
PowerManager.BRIGHTNESS_INVALID_FLOAT, /* delta= */ 0.0f);
}
@@ -253,8 +258,7 @@
// Sets the appropriate value when valid, and not equal to the current brightness
float brightnessValue = 0.3f;
mDisplayBrightnessController.updateScreenBrightnessSetting(brightnessValue);
- assertEquals(mDisplayBrightnessController.getCurrentBrightness(), brightnessValue,
- 0.0f);
+ assertEquals(mDisplayBrightnessController.getCurrentBrightness(), brightnessValue, 0.0f);
verify(mBrightnessChangeExecutor).execute(mOnBrightnessChangeRunnable);
verify(mBrightnessSetting).setBrightness(brightnessValue);
@@ -265,8 +269,7 @@
// Does nothing if the value is same as the current brightness
brightnessValue = 0.2f;
mDisplayBrightnessController.setAndNotifyCurrentScreenBrightness(brightnessValue);
- verify(mBrightnessChangeExecutor, times(2))
- .execute(mOnBrightnessChangeRunnable);
+ verify(mBrightnessChangeExecutor, times(2)).execute(mOnBrightnessChangeRunnable);
mDisplayBrightnessController.updateScreenBrightnessSetting(brightnessValue);
verifyNoMoreInteractions(mBrightnessChangeExecutor, mBrightnessSetting);
}
@@ -283,14 +286,22 @@
assertEquals(-1f, mDisplayBrightnessController.convertToAdjustedNits(brightness),
/* delta= */ 0);
- AutomaticBrightnessController automaticBrightnessController =
- mock(AutomaticBrightnessController.class);
+ AutomaticBrightnessController automaticBrightnessController = mock(
+ AutomaticBrightnessController.class);
+
+ AutomaticBrightnessStrategy automaticBrightnessStrategy =
+ mock(AutomaticBrightnessStrategy.class);
+ when(mDisplayBrightnessStrategySelector.getAutomaticBrightnessStrategy())
+ .thenReturn(automaticBrightnessStrategy);
+
when(automaticBrightnessController.convertToNits(brightness)).thenReturn(nits);
- when(automaticBrightnessController.convertToAdjustedNits(brightness))
- .thenReturn(adjustedNits);
+ when(automaticBrightnessController.convertToAdjustedNits(brightness)).thenReturn(
+ adjustedNits);
mDisplayBrightnessController.setAutomaticBrightnessController(
automaticBrightnessController);
+ verify(automaticBrightnessStrategy)
+ .setAutomaticBrightnessController(automaticBrightnessController);
assertEquals(nits, mDisplayBrightnessController.convertToNits(brightness), /* delta= */ 0);
assertEquals(adjustedNits, mDisplayBrightnessController.convertToAdjustedNits(brightness),
/* delta= */ 0);
@@ -305,12 +316,17 @@
assertEquals(PowerManager.BRIGHTNESS_INVALID_FLOAT,
mDisplayBrightnessController.getBrightnessFromNits(nits), /* delta= */ 0);
- AutomaticBrightnessController automaticBrightnessController =
- mock(AutomaticBrightnessController.class);
+ AutomaticBrightnessController automaticBrightnessController = mock(
+ AutomaticBrightnessController.class);
+ AutomaticBrightnessStrategy automaticBrightnessStrategy =
+ mock(AutomaticBrightnessStrategy.class);
+ when(mDisplayBrightnessStrategySelector.getAutomaticBrightnessStrategy())
+ .thenReturn(automaticBrightnessStrategy);
when(automaticBrightnessController.getBrightnessFromNits(nits)).thenReturn(brightness);
mDisplayBrightnessController.setAutomaticBrightnessController(
automaticBrightnessController);
-
+ verify(automaticBrightnessStrategy)
+ .setAutomaticBrightnessController(automaticBrightnessController);
assertEquals(brightness, mDisplayBrightnessController.getBrightnessFromNits(nits),
/* delta= */ 0);
}
@@ -331,8 +347,12 @@
// value
float nits = 200f;
float brightness = 0.3f;
- AutomaticBrightnessController automaticBrightnessController =
- mock(AutomaticBrightnessController.class);
+ AutomaticBrightnessController automaticBrightnessController = mock(
+ AutomaticBrightnessController.class);
+ AutomaticBrightnessStrategy automaticBrightnessStrategy =
+ mock(AutomaticBrightnessStrategy.class);
+ when(mDisplayBrightnessStrategySelector.getAutomaticBrightnessStrategy())
+ .thenReturn(automaticBrightnessStrategy);
when(automaticBrightnessController.getBrightnessFromNits(nits)).thenReturn(brightness);
when(mBrightnessSetting.getBrightnessNitsForDefaultDisplay()).thenReturn(nits);
mDisplayBrightnessController.setAutomaticBrightnessController(
@@ -375,12 +395,18 @@
float nits1 = 200f;
float brightnessValue2 = 0.5f;
float nits2 = 300f;
- AutomaticBrightnessController automaticBrightnessController =
- mock(AutomaticBrightnessController.class);
+ AutomaticBrightnessController automaticBrightnessController = mock(
+ AutomaticBrightnessController.class);
when(automaticBrightnessController.convertToNits(brightnessValue1)).thenReturn(nits1);
when(automaticBrightnessController.convertToNits(brightnessValue2)).thenReturn(nits2);
+ AutomaticBrightnessStrategy automaticBrightnessStrategy =
+ mock(AutomaticBrightnessStrategy.class);
+ when(mDisplayBrightnessStrategySelector.getAutomaticBrightnessStrategy())
+ .thenReturn(automaticBrightnessStrategy);
mDisplayBrightnessController.setAutomaticBrightnessController(
automaticBrightnessController);
+ verify(automaticBrightnessStrategy)
+ .setAutomaticBrightnessController(automaticBrightnessController);
mDisplayBrightnessController.setBrightness(brightnessValue1, 1 /* user-serial */);
verify(mBrightnessSetting).setUserSerial(1);
@@ -399,8 +425,8 @@
OffloadBrightnessStrategy offloadBrightnessStrategy = mock(OffloadBrightnessStrategy.class);
when(mDisplayBrightnessStrategySelector.getOffloadBrightnessStrategy()).thenReturn(
offloadBrightnessStrategy);
- boolean brightnessUpdated =
- mDisplayBrightnessController.setBrightnessFromOffload(brightness);
+ boolean brightnessUpdated = mDisplayBrightnessController.setBrightnessFromOffload(
+ brightness);
verify(offloadBrightnessStrategy).setOffloadScreenBrightness(brightness);
assertTrue(brightnessUpdated);
}
@@ -409,8 +435,8 @@
public void setBrightnessFromOffload_OffloadStrategyNull() {
float brightness = 0.4f;
when(mDisplayBrightnessStrategySelector.getOffloadBrightnessStrategy()).thenReturn(null);
- boolean brightnessUpdated =
- mDisplayBrightnessController.setBrightnessFromOffload(brightness);
+ boolean brightnessUpdated = mDisplayBrightnessController.setBrightnessFromOffload(
+ brightness);
assertFalse(brightnessUpdated);
}
@@ -421,9 +447,42 @@
when(offloadBrightnessStrategy.getOffloadScreenBrightness()).thenReturn(brightness);
when(mDisplayBrightnessStrategySelector.getOffloadBrightnessStrategy()).thenReturn(
offloadBrightnessStrategy);
- boolean brightnessUpdated =
- mDisplayBrightnessController.setBrightnessFromOffload(brightness);
+ boolean brightnessUpdated = mDisplayBrightnessController.setBrightnessFromOffload(
+ brightness);
verify(offloadBrightnessStrategy, never()).setOffloadScreenBrightness(brightness);
assertFalse(brightnessUpdated);
}
+
+ @Test
+ public void setupAutoBrightness_setsAutomaticStrategyAndAutoBrightnessFallbackStrategy() {
+ // Setup the strategy mocks
+ AutomaticBrightnessStrategy automaticBrightnessStrategy = mock(
+ AutomaticBrightnessStrategy.class);
+ AutoBrightnessFallbackStrategy autoBrightnessFallbackStrategy = mock(
+ AutoBrightnessFallbackStrategy.class);
+ when(mDisplayBrightnessStrategySelector.getAutomaticBrightnessStrategy())
+ .thenReturn(automaticBrightnessStrategy);
+ when(mDisplayBrightnessStrategySelector.getAutoBrightnessFallbackStrategy())
+ .thenReturn(autoBrightnessFallbackStrategy);
+
+ // Setup the argument mocks
+ AutomaticBrightnessController automaticBrightnessController = mock(
+ AutomaticBrightnessController.class);
+ SensorManager sensorManager = mock(SensorManager.class);
+ DisplayDeviceConfig displayDeviceConfig = mock(DisplayDeviceConfig.class);
+ Handler handler = mock(Handler.class);
+ BrightnessMappingStrategy brightnessMappingStrategy = mock(BrightnessMappingStrategy.class);
+ boolean isEnabled = true;
+ int leadDisplayId = 2;
+
+ mDisplayBrightnessController.setUpAutoBrightness(automaticBrightnessController,
+ sensorManager, displayDeviceConfig, handler, brightnessMappingStrategy, isEnabled,
+ leadDisplayId);
+ assertEquals(automaticBrightnessController,
+ mDisplayBrightnessController.mAutomaticBrightnessController);
+ verify(automaticBrightnessStrategy).setAutomaticBrightnessController(
+ automaticBrightnessController);
+ verify(autoBrightnessFallbackStrategy).setupAutoBrightnessFallbackSensor(sensorManager,
+ displayDeviceConfig, handler, brightnessMappingStrategy, isEnabled, leadDisplayId);
+ }
}
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/DisplayBrightnessStrategySelectorTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/DisplayBrightnessStrategySelectorTest.java
index f270650..ae6361b 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/brightness/DisplayBrightnessStrategySelectorTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/DisplayBrightnessStrategySelectorTest.java
@@ -40,9 +40,11 @@
import com.android.internal.R;
import com.android.internal.util.test.FakeSettingsProvider;
import com.android.internal.util.test.FakeSettingsProviderRule;
+import com.android.server.display.brightness.strategy.AutoBrightnessFallbackStrategy;
import com.android.server.display.brightness.strategy.AutomaticBrightnessStrategy;
import com.android.server.display.brightness.strategy.AutomaticBrightnessStrategy2;
import com.android.server.display.brightness.strategy.BoostBrightnessStrategy;
+import com.android.server.display.brightness.strategy.DisplayBrightnessStrategy;
import com.android.server.display.brightness.strategy.DozeBrightnessStrategy;
import com.android.server.display.brightness.strategy.FollowerBrightnessStrategy;
import com.android.server.display.brightness.strategy.InvalidBrightnessStrategy;
@@ -86,6 +88,8 @@
@Mock
private OffloadBrightnessStrategy mOffloadBrightnessStrategy;
@Mock
+ private AutoBrightnessFallbackStrategy mAutoBrightnessFallbackStrategy;
+ @Mock
private Resources mResources;
@Mock
private DisplayManagerFlags mDisplayManagerFlags;
@@ -146,6 +150,11 @@
DisplayManagerFlags displayManagerFlags) {
return mOffloadBrightnessStrategy;
}
+
+ @Override
+ AutoBrightnessFallbackStrategy getAutoBrightnessFallbackStrategy() {
+ return mAutoBrightnessFallbackStrategy;
+ }
};
@Rule
@@ -187,8 +196,8 @@
when(mResources.getBoolean(R.bool.config_allowAutoBrightnessWhileDozing)).thenReturn(
DISALLOW_AUTO_BRIGHTNESS_WHILE_DOZING);
assertNotEquals(mDisplayBrightnessStrategySelector.selectStrategy(
- new StrategySelectionRequest(displayPowerRequest, Display.STATE_DOZE,
- 0.1f, false)),
+ new StrategySelectionRequest(displayPowerRequest, Display.STATE_DOZE,
+ 0.1f, false)),
mDozeBrightnessModeStrategy);
}
@@ -309,6 +318,26 @@
}
@Test
+ public void selectStrategy_selectsAutomaticFallbackStrategyWhenValid() {
+ when(mDisplayManagerFlags.isRefactorDisplayPowerControllerEnabled()).thenReturn(true);
+ mDisplayBrightnessStrategySelector = new DisplayBrightnessStrategySelector(mContext,
+ mInjector, DISPLAY_ID, mDisplayManagerFlags);
+ DisplayManagerInternal.DisplayPowerRequest displayPowerRequest = mock(
+ DisplayManagerInternal.DisplayPowerRequest.class);
+ displayPowerRequest.policy = DisplayManagerInternal.DisplayPowerRequest.POLICY_BRIGHT;
+ displayPowerRequest.screenBrightnessOverride = Float.NaN;
+ when(mFollowerBrightnessStrategy.getBrightnessToFollow()).thenReturn(Float.NaN);
+ when(mTemporaryBrightnessStrategy.getTemporaryScreenBrightness()).thenReturn(Float.NaN);
+ when(mAutomaticBrightnessStrategy.shouldUseAutoBrightness()).thenReturn(true);
+ when(mAutomaticBrightnessStrategy.isAutoBrightnessValid()).thenReturn(false);
+ when(mAutoBrightnessFallbackStrategy.isValid()).thenReturn(true);
+ assertEquals(mDisplayBrightnessStrategySelector.selectStrategy(
+ new StrategySelectionRequest(displayPowerRequest, Display.STATE_ON,
+ 0.1f, false)),
+ mAutoBrightnessFallbackStrategy);
+ }
+
+ @Test
public void selectStrategyDoesNotSelectOffloadStrategyWhenFeatureFlagDisabled() {
when(mDisplayManagerFlags.isDisplayOffloadEnabled()).thenReturn(false);
mDisplayBrightnessStrategySelector = new DisplayBrightnessStrategySelector(mContext,
@@ -341,23 +370,15 @@
StrategySelectionNotifyRequest strategySelectionNotifyRequest =
new StrategySelectionNotifyRequest(displayPowerRequest, Display.STATE_ON,
mFollowerBrightnessStrategy, 0.1f,
- false, false);
- verify(mInvalidBrightnessStrategy).strategySelectionPostProcessor(
- eq(strategySelectionNotifyRequest));
- verify(mScreenOffBrightnessModeStrategy).strategySelectionPostProcessor(
- eq(strategySelectionNotifyRequest));
- verify(mDozeBrightnessModeStrategy).strategySelectionPostProcessor(
- eq(strategySelectionNotifyRequest));
- verify(mFollowerBrightnessStrategy).strategySelectionPostProcessor(
- eq(strategySelectionNotifyRequest));
- verify(mBoostBrightnessStrategy).strategySelectionPostProcessor(
- eq(strategySelectionNotifyRequest));
- verify(mOverrideBrightnessStrategy).strategySelectionPostProcessor(
- eq(strategySelectionNotifyRequest));
- verify(mTemporaryBrightnessStrategy).strategySelectionPostProcessor(
- eq(strategySelectionNotifyRequest));
- verify(mAutomaticBrightnessStrategy).strategySelectionPostProcessor(
- eq(strategySelectionNotifyRequest));
+ false, false, false);
+
+ for (DisplayBrightnessStrategy displayBrightnessStrategy :
+ mDisplayBrightnessStrategySelector.mDisplayBrightnessStrategies) {
+ if (displayBrightnessStrategy != null) {
+ verify(displayBrightnessStrategy).strategySelectionPostProcessor(
+ eq(strategySelectionNotifyRequest));
+ }
+ }
}
@Test
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutoBrightnessFallbackStrategyTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutoBrightnessFallbackStrategyTest.java
new file mode 100644
index 0000000..7a6a911
--- /dev/null
+++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutoBrightnessFallbackStrategyTest.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.display.brightness.strategy;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.hardware.Sensor;
+import android.hardware.SensorManager;
+import android.hardware.display.DisplayManagerInternal;
+import android.os.Handler;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.server.display.BrightnessMappingStrategy;
+import com.android.server.display.DisplayBrightnessState;
+import com.android.server.display.DisplayDeviceConfig;
+import com.android.server.display.ScreenOffBrightnessSensorController;
+import com.android.server.display.brightness.BrightnessReason;
+import com.android.server.display.brightness.StrategyExecutionRequest;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class AutoBrightnessFallbackStrategyTest {
+ private AutoBrightnessFallbackStrategy mAutoBrightnessFallbackStrategy;
+
+ @Mock
+ private Sensor mScreenOffBrightnessSensor;
+
+ @Mock
+ private ScreenOffBrightnessSensorController mScreenOffBrightnessSensorController;
+
+ @Before
+ public void before() {
+ MockitoAnnotations.initMocks(this);
+ mAutoBrightnessFallbackStrategy = new AutoBrightnessFallbackStrategy(
+ new AutoBrightnessFallbackStrategy.Injector() {
+ @Override
+ public Sensor getScreenOffBrightnessSensor(SensorManager sensorManager,
+ DisplayDeviceConfig displayDeviceConfig) {
+ return mScreenOffBrightnessSensor;
+ }
+
+ @Override
+ public ScreenOffBrightnessSensorController
+ getScreenOffBrightnessSensorController(SensorManager sensorManager,
+ Sensor lightSensor, Handler handler,
+ ScreenOffBrightnessSensorController.Clock clock,
+ int[] sensorValueToLux,
+ BrightnessMappingStrategy brightnessMapper) {
+ return mScreenOffBrightnessSensorController;
+ }
+ });
+ }
+
+ @Test
+ public void testUpdateBrightnessWhenScreenDozeStateIsRequested() {
+ // Setup the argument mocks
+ SensorManager sensorManager = mock(SensorManager.class);
+ DisplayDeviceConfig displayDeviceConfig = mock(DisplayDeviceConfig.class);
+ Handler handler = mock(Handler.class);
+ BrightnessMappingStrategy brightnessMappingStrategy = mock(BrightnessMappingStrategy.class);
+ boolean isEnabled = true;
+ int leadDisplayId = 2;
+
+ int[] sensorValueToLux = new int[]{50, 100};
+ when(displayDeviceConfig.getScreenOffBrightnessSensorValueToLux()).thenReturn(
+ sensorValueToLux);
+
+ mAutoBrightnessFallbackStrategy.setupAutoBrightnessFallbackSensor(sensorManager,
+ displayDeviceConfig, handler, brightnessMappingStrategy, isEnabled, leadDisplayId);
+
+ assertEquals(mScreenOffBrightnessSensor,
+ mAutoBrightnessFallbackStrategy.mScreenOffBrightnessSensor);
+ assertEquals(mScreenOffBrightnessSensorController,
+ mAutoBrightnessFallbackStrategy.getScreenOffBrightnessSensorController());
+
+ DisplayManagerInternal.DisplayPowerRequest
+ displayPowerRequest = new DisplayManagerInternal.DisplayPowerRequest();
+ float fallbackBrightness = 0.2f;
+ when(mScreenOffBrightnessSensorController.getAutomaticScreenBrightness()).thenReturn(
+ fallbackBrightness);
+
+ BrightnessReason brightnessReason = new BrightnessReason();
+ brightnessReason.setReason(BrightnessReason.REASON_SCREEN_OFF_BRIGHTNESS_SENSOR);
+ DisplayBrightnessState expectedDisplayBrightnessState =
+ new DisplayBrightnessState.Builder()
+ .setBrightness(fallbackBrightness)
+ .setBrightnessReason(brightnessReason)
+ .setSdrBrightness(fallbackBrightness)
+ .setDisplayBrightnessStrategyName(mAutoBrightnessFallbackStrategy.getName())
+ .build();
+ DisplayBrightnessState updatedDisplayBrightnessState =
+ mAutoBrightnessFallbackStrategy.updateBrightness(
+ new StrategyExecutionRequest(displayPowerRequest, 0.2f));
+ assertEquals(updatedDisplayBrightnessState, expectedDisplayBrightnessState);
+ }
+
+}
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy2Test.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy2Test.java
index fd43720..09f5bb6 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy2Test.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy2Test.java
@@ -343,7 +343,7 @@
AutomaticBrightnessController.class);
when(automaticBrightnessController.getAutomaticScreenBrightness(any(BrightnessEvent.class)))
.thenReturn(automaticScreenBrightness);
- when(automaticBrightnessController.getAutomaticScreenBrightnessBasedOnLastObservedLux(
+ when(automaticBrightnessController.getAutomaticScreenBrightnessBasedOnLastUsedLux(
any(BrightnessEvent.class)))
.thenReturn(automaticScreenBrightness);
mAutomaticBrightnessStrategy.setAutomaticBrightnessController(
@@ -352,7 +352,7 @@
mAutomaticBrightnessStrategy.getAutomaticScreenBrightness(
new BrightnessEvent(DISPLAY_ID)), 0.0f);
assertEquals(automaticScreenBrightness,
- mAutomaticBrightnessStrategy.getAutomaticScreenBrightnessBasedOnLastObservedLux(
+ mAutomaticBrightnessStrategy.getAutomaticScreenBrightnessBasedOnLastUsedLux(
new BrightnessEvent(DISPLAY_ID)), 0.0f);
}
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategyTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategyTest.java
index 54f2268..3e78118 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategyTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategyTest.java
@@ -341,7 +341,7 @@
AutomaticBrightnessController.class);
when(automaticBrightnessController.getAutomaticScreenBrightness(any(BrightnessEvent.class)))
.thenReturn(automaticScreenBrightness);
- when(automaticBrightnessController.getAutomaticScreenBrightnessBasedOnLastObservedLux(
+ when(automaticBrightnessController.getAutomaticScreenBrightnessBasedOnLastUsedLux(
any(BrightnessEvent.class)))
.thenReturn(automaticScreenBrightness);
mAutomaticBrightnessStrategy.setAutomaticBrightnessController(
@@ -350,7 +350,7 @@
mAutomaticBrightnessStrategy.getAutomaticScreenBrightness(
new BrightnessEvent(DISPLAY_ID)), 0.0f);
assertEquals(automaticScreenBrightness,
- mAutomaticBrightnessStrategy.getAutomaticScreenBrightnessBasedOnLastObservedLux(
+ mAutomaticBrightnessStrategy.getAutomaticScreenBrightnessBasedOnLastUsedLux(
new BrightnessEvent(DISPLAY_ID)), 0.0f);
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceContentTest.java b/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceContentTest.java
index 7aafa8e..5ddd8a5 100644
--- a/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceContentTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceContentTest.java
@@ -26,7 +26,6 @@
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
import android.content.pm.PackageManagerInternal;
import android.media.projection.MediaProjectionInfo;
@@ -108,7 +107,7 @@
mMediaPorjectionCallback.onStart(exemptedRecorderPackage);
mSensitiveContentProtectionManagerService.setSensitiveContentProtection(
mPackageInfo.getWindowToken(), mPackageInfo.getPkg(), mPackageInfo.getUid(), true);
- verifyZeroInteractions(mWindowManager);
+ verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture());
}
@Test
@@ -135,7 +134,7 @@
// when screen sharing is not active, no app window should be blocked.
mSensitiveContentProtectionManagerService.setSensitiveContentProtection(
mPackageInfo.getWindowToken(), mPackageInfo.getPkg(), mPackageInfo.getUid(), true);
- verifyZeroInteractions(mWindowManager);
+ verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture());
}
@Test
@@ -158,8 +157,7 @@
mMediaPorjectionCallback.onStart(mMediaProjectionInfo);
mSensitiveContentProtectionManagerService.setSensitiveContentProtection(
mPackageInfo.getWindowToken(), mPackageInfo.getPkg(), mPackageInfo.getUid(), true);
- verify(mWindowManager, never())
- .addBlockScreenCaptureForApps(mPackageInfoCaptor.capture());
+ verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture());
}
@Test
@@ -168,7 +166,7 @@
mMediaProjectionCallbackCaptor.getValue().onStart(mMediaProjectionInfo);
mSensitiveContentProtectionManagerService.setSensitiveContentProtection(
mPackageInfo.getWindowToken(), mPackageInfo.getPkg(), mPackageInfo.getUid(), true);
- verifyZeroInteractions(mWindowManager);
+ verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture());
}
private void mockDisabledViaDeveloperOption() {
diff --git a/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceNotificationTest.java b/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceNotificationTest.java
index a20d935..8b65337 100644
--- a/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceNotificationTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceNotificationTest.java
@@ -30,7 +30,6 @@
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import android.content.pm.PackageManagerInternal;
@@ -102,6 +101,8 @@
@Captor
ArgumentCaptor<MediaProjectionManager.Callback> mMediaProjectionCallbackCaptor;
+ @Captor
+ private ArgumentCaptor<ArraySet<PackageInfo>> mPackageInfoCaptor;
@Mock
private MediaProjectionManager mProjectionManager;
@@ -309,7 +310,7 @@
mMediaProjectionCallbackCaptor.getValue().onStart(mediaProjectionInfo);
- verifyZeroInteractions(mWindowManager);
+ verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture());
}
@Test
@@ -469,7 +470,7 @@
mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo());
- verifyZeroInteractions(mWindowManager);
+ verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture());
}
@Test
@@ -480,7 +481,7 @@
mSensitiveContentProtectionManagerService.mNotificationListener.onListenerConnected();
- verifyZeroInteractions(mWindowManager);
+ verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture());
}
@Test
@@ -495,7 +496,7 @@
mSensitiveContentProtectionManagerService.mNotificationListener.onListenerConnected();
- verifyZeroInteractions(mWindowManager);
+ verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture());
}
@Test
@@ -519,7 +520,7 @@
mSensitiveContentProtectionManagerService.mNotificationListener.onListenerConnected();
- verifyZeroInteractions(mWindowManager);
+ verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture());
}
@Test
@@ -530,7 +531,7 @@
mSensitiveContentProtectionManagerService.mNotificationListener.onListenerConnected();
- verifyZeroInteractions(mWindowManager);
+ verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture());
}
@Test
@@ -541,7 +542,7 @@
mSensitiveContentProtectionManagerService.mNotificationListener.onListenerConnected();
- verifyZeroInteractions(mWindowManager);
+ verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture());
}
@Test
@@ -557,7 +558,7 @@
mSensitiveContentProtectionManagerService.mNotificationListener.onListenerConnected();
- verifyZeroInteractions(mWindowManager);
+ verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture());
}
@Test
@@ -574,7 +575,7 @@
mSensitiveContentProtectionManagerService.mNotificationListener.onListenerConnected();
- verifyZeroInteractions(mWindowManager);
+ verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture());
}
@Test
@@ -586,7 +587,7 @@
mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo());
mSensitiveContentProtectionManagerService.mNotificationListener.onListenerConnected();
- verifyZeroInteractions(mWindowManager);
+ verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture());
}
@Test
@@ -598,7 +599,7 @@
mSensitiveContentProtectionManagerService.mNotificationListener
.onNotificationRankingUpdate(mRankingMap);
- verifyZeroInteractions(mWindowManager);
+ verifyNoBlockOrClearInteractionWithWindowManager();
}
@Test
@@ -614,7 +615,7 @@
mSensitiveContentProtectionManagerService.mNotificationListener
.onNotificationRankingUpdate(mRankingMap);
- verifyZeroInteractions(mWindowManager);
+ verifyNoBlockOrClearInteractionWithWindowManager();
}
@Test
@@ -640,7 +641,7 @@
mSensitiveContentProtectionManagerService.mNotificationListener
.onNotificationRankingUpdate(mRankingMap);
- verifyZeroInteractions(mWindowManager);
+ verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture());
}
@Test
@@ -652,7 +653,7 @@
mSensitiveContentProtectionManagerService.mNotificationListener
.onNotificationRankingUpdate(mRankingMap);
- verifyZeroInteractions(mWindowManager);
+ verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture());
}
@Test
@@ -666,7 +667,7 @@
mSensitiveContentProtectionManagerService.mNotificationListener
.onNotificationRankingUpdate(null);
- verifyZeroInteractions(mWindowManager);
+ verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture());
}
@Test
@@ -684,7 +685,7 @@
mSensitiveContentProtectionManagerService.mNotificationListener
.onNotificationRankingUpdate(mRankingMap);
- verifyZeroInteractions(mWindowManager);
+ verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture());
}
@Test
@@ -702,7 +703,7 @@
mSensitiveContentProtectionManagerService.mNotificationListener
.onNotificationRankingUpdate(mRankingMap);
- verifyZeroInteractions(mWindowManager);
+ verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture());
}
@Test
@@ -715,7 +716,7 @@
mSensitiveContentProtectionManagerService.mNotificationListener
.onNotificationRankingUpdate(mRankingMap);
- verifyZeroInteractions(mWindowManager);
+ verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture());
}
@Test
@@ -727,7 +728,7 @@
mSensitiveContentProtectionManagerService.mNotificationListener
.onNotificationPosted(mNotification1, mRankingMap);
- verifyZeroInteractions(mWindowManager);
+ verifyNoBlockOrClearInteractionWithWindowManager();
}
@Test
@@ -743,7 +744,7 @@
mSensitiveContentProtectionManagerService.mNotificationListener
.onNotificationPosted(mNotification1, mRankingMap);
- verifyZeroInteractions(mWindowManager);
+ verifyNoBlockOrClearInteractionWithWindowManager();
}
@Test
@@ -773,7 +774,7 @@
mSensitiveContentProtectionManagerService.mNotificationListener
.onNotificationPosted(mNotification2, mRankingMap);
- verifyZeroInteractions(mWindowManager);
+ verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture());
}
@Test
@@ -787,7 +788,7 @@
mSensitiveContentProtectionManagerService.mNotificationListener
.onNotificationPosted(null, mRankingMap);
- verifyZeroInteractions(mWindowManager);
+ verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture());
}
@Test
@@ -801,7 +802,7 @@
mSensitiveContentProtectionManagerService.mNotificationListener
.onNotificationPosted(mNotification1, null);
- verifyZeroInteractions(mWindowManager);
+ verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture());
}
@Test
@@ -816,7 +817,7 @@
mSensitiveContentProtectionManagerService.mNotificationListener
.onNotificationPosted(mNotification1, mRankingMap);
- verifyZeroInteractions(mWindowManager);
+ verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture());
}
@Test
@@ -829,7 +830,14 @@
mSensitiveContentProtectionManagerService.mNotificationListener
.onNotificationPosted(mNotification1, mRankingMap);
- verifyZeroInteractions(mWindowManager);
+ verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture());
+ }
+
+ private void verifyNoBlockOrClearInteractionWithWindowManager() {
+ verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture());
+ verify(mWindowManager, never()).clearBlockedApps();
+ verify(mWindowManager, never())
+ .removeBlockScreenCaptureForApps(mPackageInfoCaptor.capture());
}
private void mockDisabledViaDevelopOption() {
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java
index 16d05b1..6e6d5a8 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java
@@ -89,6 +89,7 @@
import android.os.Process;
import android.os.RemoteCallback;
import android.os.RemoteException;
+import android.os.test.FakePermissionEnforcer;
import android.util.Pair;
import android.view.Display;
import android.view.KeyEvent;
@@ -181,6 +182,7 @@
@Mock private FingerprintGestureDispatcher mMockFingerprintGestureDispatcher;
@Mock private MagnificationProcessor mMockMagnificationProcessor;
@Mock private RemoteCallback.OnResultListener mMockListener;
+ FakePermissionEnforcer mFakePermissionEnforcer = new FakePermissionEnforcer();
@Before
public void setup() {
@@ -198,6 +200,8 @@
PowerManager powerManager =
new PowerManager(mMockContext, mMockIPowerManager, mMockIThermalService, mHandler);
when(mMockContext.getSystemService(Context.POWER_SERVICE)).thenReturn(powerManager);
+ when(mMockContext.getSystemService(Context.PERMISSION_ENFORCER_SERVICE))
+ .thenReturn(mFakePermissionEnforcer);
when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
when(mMockPackageManager.hasSystemFeature(FEATURE_FINGERPRINT)).thenReturn(true);
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java
index cda8b01..c4946f0 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java
@@ -26,7 +26,6 @@
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.notNull;
-import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
@@ -56,6 +55,7 @@
import android.os.IBinder;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.os.test.FakePermissionEnforcer;
import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
@@ -82,7 +82,6 @@
import java.util.HashSet;
import java.util.List;
-
/**
* Tests for AccessibilityServiceConnection
*/
@@ -130,6 +129,7 @@
IBrailleDisplayController mMockBrailleDisplayController;
@Mock
MotionEventInjector mMockMotionEventInjector;
+ FakePermissionEnforcer mFakePermissionEnforcer = new FakePermissionEnforcer();
MessageCapturingHandler mHandler = new MessageCapturingHandler(null);
@@ -151,12 +151,14 @@
when(mMockA11yTrace.isA11yTracingEnabled()).thenReturn(false);
when(mMockContext.getSystemService(Context.DISPLAY_SERVICE))
.thenReturn(new DisplayManager(mMockContext));
+ when(mMockContext.getSystemService(Context.PERMISSION_ENFORCER_SERVICE))
+ .thenReturn(mFakePermissionEnforcer);
mConnection = new AccessibilityServiceConnection(mMockUserState, mMockContext,
- COMPONENT_NAME, mServiceInfo, SERVICE_ID, mHandler, new Object(),
- mMockSecurityPolicy, mMockSystemSupport, mMockA11yTrace,
- mMockWindowManagerInternal, mMockSystemActionPerformer,
- mMockA11yWindowManager, mMockActivityTaskManagerInternal);
+ COMPONENT_NAME, mServiceInfo, SERVICE_ID, mHandler, new Object(),
+ mMockSecurityPolicy, mMockSystemSupport, mMockA11yTrace,
+ mMockWindowManagerInternal, mMockSystemActionPerformer,
+ mMockA11yWindowManager, mMockActivityTaskManagerInternal);
when(mMockSecurityPolicy.canPerformGestures(mConnection)).thenReturn(true);
when(mMockSecurityPolicy.checkAccessibilityAccess(mConnection)).thenReturn(true);
}
@@ -317,6 +319,8 @@
@Test
@RequiresFlagsEnabled(android.view.accessibility.Flags.FLAG_BRAILLE_DISPLAY_HID)
public void connectBluetoothBrailleDisplay() throws Exception {
+ mFakePermissionEnforcer.grant(Manifest.permission.BLUETOOTH_CONNECT);
+ mFakePermissionEnforcer.grant(Manifest.permission.MANAGE_ACCESSIBILITY);
final String macAddress = "00:11:22:33:AA:BB";
final byte[] descriptor = {0x05, 0x41};
Bundle bd = new Bundle();
@@ -338,9 +342,6 @@
@Test
@RequiresFlagsEnabled(android.view.accessibility.Flags.FLAG_BRAILLE_DISPLAY_HID)
public void connectBluetoothBrailleDisplay_throwsForMissingBluetoothConnectPermission() {
- doThrow(SecurityException.class).when(mMockContext)
- .enforceCallingPermission(eq(Manifest.permission.BLUETOOTH_CONNECT), any());
-
assertThrows(SecurityException.class,
() -> mConnection.connectBluetoothBrailleDisplay("unused",
mMockBrailleDisplayController));
@@ -349,6 +350,7 @@
@Test
@RequiresFlagsEnabled(android.view.accessibility.Flags.FLAG_BRAILLE_DISPLAY_HID)
public void connectBluetoothBrailleDisplay_throwsForNullMacAddress() {
+ mFakePermissionEnforcer.grant(Manifest.permission.BLUETOOTH_CONNECT);
assertThrows(NullPointerException.class,
() -> mConnection.connectBluetoothBrailleDisplay(null,
mMockBrailleDisplayController));
@@ -357,6 +359,7 @@
@Test
@RequiresFlagsEnabled(android.view.accessibility.Flags.FLAG_BRAILLE_DISPLAY_HID)
public void connectBluetoothBrailleDisplay_throwsForMisformattedMacAddress() {
+ mFakePermissionEnforcer.grant(Manifest.permission.BLUETOOTH_CONNECT);
assertThrows(IllegalArgumentException.class,
() -> mConnection.connectBluetoothBrailleDisplay("12:34",
mMockBrailleDisplayController));
@@ -365,6 +368,7 @@
@Test
@RequiresFlagsEnabled(android.view.accessibility.Flags.FLAG_BRAILLE_DISPLAY_HID)
public void connectUsbBrailleDisplay() throws Exception {
+ mFakePermissionEnforcer.grant(Manifest.permission.MANAGE_ACCESSIBILITY);
final String serialNumber = "myUsbDevice";
final byte[] descriptor = {0x05, 0x41};
Bundle bd = new Bundle();
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/ProxyAccessibilityServiceConnectionTest.java b/services/tests/servicestests/src/com/android/server/accessibility/ProxyAccessibilityServiceConnectionTest.java
index 3d0db71..c0e5f76 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/ProxyAccessibilityServiceConnectionTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/ProxyAccessibilityServiceConnectionTest.java
@@ -38,6 +38,7 @@
import android.content.res.Resources;
import android.graphics.Color;
import android.os.Handler;
+import android.os.test.FakePermissionEnforcer;
import android.view.accessibility.AccessibilityEvent;
import com.android.server.wm.WindowManagerInternal;
@@ -79,6 +80,7 @@
AccessibilityTrace mMockA11yTrace;
@Mock
WindowManagerInternal mMockWindowManagerInternal;
+ FakePermissionEnforcer mFakePermissionEnforcer = new FakePermissionEnforcer();
ProxyAccessibilityServiceConnection mProxyConnection;
AccessibilityServiceInfo mAccessibilityServiceInfo;
private int mFocusStrokeWidthDefaultValue;
@@ -90,6 +92,8 @@
MockitoAnnotations.initMocks(this);
when(mMockContext.getResources()).thenReturn(resources);
when(mMockSecurityPolicy.checkAccessibilityAccess(any())).thenReturn(true);
+ when(mMockContext.getSystemService(Context.PERMISSION_ENFORCER_SERVICE))
+ .thenReturn(mFakePermissionEnforcer);
mAccessibilityServiceInfo = new AccessibilityServiceInfo();
mProxyConnection = new ProxyAccessibilityServiceConnection(mMockContext, COMPONENT_NAME,
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/ProxyManagerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/ProxyManagerTest.java
index f1b356a..52b33db 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/ProxyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/ProxyManagerTest.java
@@ -50,6 +50,7 @@
import android.os.IBinder;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
+import android.os.test.FakePermissionEnforcer;
import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
@@ -113,6 +114,7 @@
@Mock private IBinder mMockServiceAsBinder;
@Mock private VirtualDeviceManagerInternal mMockVirtualDeviceManagerInternal;
@Mock private IVirtualDeviceManager mMockIVirtualDeviceManager;
+ FakePermissionEnforcer mFakePermissionEnforcer = new FakePermissionEnforcer();
private int mFocusStrokeWidthDefaultValue;
private int mFocusColorDefaultValue;
@@ -132,6 +134,8 @@
when(mMockContext.getMainExecutor())
.thenReturn(InstrumentationRegistry.getTargetContext().getMainExecutor());
+ when(mMockContext.getSystemService(Context.PERMISSION_ENFORCER_SERVICE))
+ .thenReturn(mFakePermissionEnforcer);
when(mMockVirtualDeviceManagerInternal.getDeviceIdsForUid(anyInt())).thenReturn(
new ArraySet(Set.of(DEVICE_ID)));
LocalServices.removeServiceForTest(VirtualDeviceManagerInternal.class);
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/UiAutomationManagerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/UiAutomationManagerTest.java
index 95a1f5a..e24592e 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/UiAutomationManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/UiAutomationManagerTest.java
@@ -39,6 +39,7 @@
import android.content.pm.ServiceInfo;
import android.hardware.display.DisplayManager;
import android.os.IBinder;
+import android.os.test.FakePermissionEnforcer;
import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.view.WindowManager;
@@ -80,12 +81,15 @@
@Mock IBinder mMockOwner;
@Mock IAccessibilityServiceClient mMockAccessibilityServiceClient;
@Mock IBinder mMockServiceAsBinder;
+ FakePermissionEnforcer mFakePermissionEnforcer = new FakePermissionEnforcer();
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
when(mMockSystemSupport.getKeyEventDispatcher()).thenReturn(mock(KeyEventDispatcher.class));
+ when(mMockContext.getSystemService(Context.PERMISSION_ENFORCER_SERVICE))
+ .thenReturn(mFakePermissionEnforcer);
when(mMockServiceInfo.getResolveInfo()).thenReturn(mMockResolveInfo);
mMockResolveInfo.serviceInfo = mock(ServiceInfo.class);
diff --git a/services/tests/servicestests/src/com/android/server/autofill/OWNERS b/services/tests/servicestests/src/com/android/server/autofill/OWNERS
new file mode 100644
index 0000000..70106d1
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/autofill/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/view/autofill/OWNERS
\ No newline at end of file
diff --git a/services/tests/servicestests/src/com/android/server/autofill/SaveEventLoggerTest.java b/services/tests/servicestests/src/com/android/server/autofill/SaveEventLoggerTest.java
new file mode 100644
index 0000000..9e52078
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/autofill/SaveEventLoggerTest.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.autofill;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.ArgumentCaptor;
+
+@RunWith(JUnit4.class)
+public class SaveEventLoggerTest {
+
+ @Test
+ public void testTimestampsInitialized() {
+ SaveEventLogger mLogger = spy(SaveEventLogger.forSessionId(1, 1));
+
+ mLogger.maybeSetLatencySaveUiDisplayMillis();
+ mLogger.maybeSetLatencySaveRequestMillis();
+ mLogger.maybeSetLatencySaveFinishMillis();
+
+ ArgumentCaptor<Long> latencySaveUiDisplayMillis = ArgumentCaptor.forClass(Long.class);
+ ArgumentCaptor<Long> latencySaveRequestMillis = ArgumentCaptor.forClass(Long.class);
+ ArgumentCaptor<Long> latencySaveFinishMillis = ArgumentCaptor.forClass(Long.class);
+
+ verify(mLogger, times(1))
+ .maybeSetLatencySaveUiDisplayMillis(latencySaveUiDisplayMillis.capture());
+ verify(mLogger, times(1))
+ .maybeSetLatencySaveRequestMillis(latencySaveRequestMillis.capture());
+ verify(mLogger, times(1))
+ .maybeSetLatencySaveFinishMillis(latencySaveFinishMillis.capture());
+
+ assertThat(latencySaveUiDisplayMillis.getValue())
+ .isNotEqualTo(SaveEventLogger.UNINITIATED_TIMESTAMP);
+ assertThat(latencySaveRequestMillis.getValue())
+ .isNotEqualTo(SaveEventLogger.UNINITIATED_TIMESTAMP);
+ assertThat(latencySaveFinishMillis.getValue())
+ .isNotEqualTo(SaveEventLogger.UNINITIATED_TIMESTAMP);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
index 855c658..b4cc343 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
@@ -441,11 +441,6 @@
@Override
public void runCryptoSelfTest() {}
- @Override
- public String[] getPersonalAppsForSuspension(int userId) {
- return new String[]{};
- }
-
public void setSystemCurrentTimeMillis(long value) {
mCurrentTimeMillis = value;
}
diff --git a/services/tests/servicestests/src/com/android/server/grammaticalinflection/GrammaticalInflectionBackupTest.java b/services/tests/servicestests/src/com/android/server/grammaticalinflection/GrammaticalInflectionBackupTest.java
index af6f6f2..608b306 100644
--- a/services/tests/servicestests/src/com/android/server/grammaticalinflection/GrammaticalInflectionBackupTest.java
+++ b/services/tests/servicestests/src/com/android/server/grammaticalinflection/GrammaticalInflectionBackupTest.java
@@ -112,7 +112,7 @@
public void testSystemBackupPayload_returnsGender()
throws IOException, ClassNotFoundException {
doReturn(Configuration.GRAMMATICAL_GENDER_MASCULINE).when(mGrammaticalInflectionService)
- .getSystemGrammaticalGender(any(), eq(DEFAULT_USER_ID));
+ .getSystemGrammaticalGender(eq(DEFAULT_USER_ID));
int gender = convertByteArrayToInt(mBackupHelper.getSystemBackupPayload(DEFAULT_USER_ID));
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java
index 902ffed..4faeea5 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java
@@ -937,6 +937,94 @@
}
@Test
+ public void onHotplug_doNotSend_systemAudioModeRequestWithParameter(){
+ // Add a device to the network and assert that this device is included in the list of
+ // devices.
+ HdmiDeviceInfo infoAudioSystem = HdmiDeviceInfo.cecDeviceBuilder()
+ .setLogicalAddress(ADDR_AUDIO_SYSTEM)
+ .setPhysicalAddress(0x2000)
+ .setPortId(2)
+ .setDeviceType(HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM)
+ .setVendorId(0x1000)
+ .setDisplayName("Audio System")
+ .build();
+ mHdmiControlService.getHdmiCecNetwork().addCecDevice(infoAudioSystem);
+ mTestLooper.dispatchAll();
+ assertThat(mHdmiControlService.getHdmiCecNetwork().getDeviceInfoList(false))
+ .hasSize(1);
+ mDeviceEventListeners.clear();
+ assertThat(mDeviceEventListeners.size()).isEqualTo(0);
+
+ // Connect port 2 (ARC port)
+ mNativeWrapper.setPortConnectionStatus(2, true);
+
+ // AVR connection
+ HdmiCecMessage initiateArc = HdmiCecMessageBuilder.buildInitiateArc(
+ ADDR_AUDIO_SYSTEM,
+ ADDR_TV);
+
+ mNativeWrapper.onCecMessage(initiateArc);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage reportArcInitiated = HdmiCecMessageBuilder.buildReportArcInitiated(
+ ADDR_TV,
+ ADDR_AUDIO_SYSTEM);
+ // <Report ARC Initiated> should only be sent after SAD querying is done
+ assertThat(mNativeWrapper.getResultMessages()).doesNotContain(reportArcInitiated);
+ // Finish querying SADs
+ assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY);
+ mNativeWrapper.clearResultMessages();
+ mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+ assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY);
+ mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+
+ assertThat(mNativeWrapper.getResultMessages()).contains(reportArcInitiated);
+ mNativeWrapper.clearResultMessages();
+
+ // Audio System still acking polls. Allowing detection by HotplugDetectionAction
+ mNativeWrapper.setPollAddressResponse(ADDR_AUDIO_SYSTEM, SendMessageResult.SUCCESS);
+ mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+
+ // Hotplug event
+ mHdmiCecLocalDeviceTv.onHotplug(2, true);
+
+ // Audio System replies to <Give System Audio Mode> with <System Audio Mode Status>[On]
+ HdmiCecMessage reportSystemAudioModeOn =
+ HdmiCecMessageBuilder.buildReportSystemAudioMode(
+ ADDR_AUDIO_SYSTEM,
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ true);
+ mHdmiControlService.handleCecCommand(reportSystemAudioModeOn);
+ mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+
+ // Hotplug event when turn off the audio system
+ mHdmiCecLocalDeviceTv.onHotplug(2, false);
+ mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+
+ // Some audio systems (eg. Sony) might trigger 5V status from false to true when the
+ // devices are off
+ mHdmiCecLocalDeviceTv.onHotplug(2, true);
+
+ // Audio System replies to <Give System Audio Mode> with <System Audio Mode Status>
+ HdmiCecMessage reportSystemAudioMode =
+ HdmiCecMessageBuilder.buildReportSystemAudioMode(
+ ADDR_AUDIO_SYSTEM,
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ true);
+ mHdmiControlService.handleCecCommand(reportSystemAudioMode);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage systemAudioModeRequest = HdmiCecMessageBuilder.buildSystemAudioModeRequest(
+ mTvLogicalAddress, ADDR_AUDIO_SYSTEM, mTvPhysicalAddress, true);
+ assertThat(mNativeWrapper.getResultMessages()).doesNotContain(systemAudioModeRequest);
+ }
+
+ @Test
public void listenerInvokedIfPhysicalAddressReported() {
mHdmiControlService.getHdmiCecNetwork().clearDeviceList();
assertThat(mHdmiControlService.getHdmiCecNetwork().getDeviceInfoList(false))
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
index 1d3dacc..e1b66b5 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
@@ -106,6 +106,7 @@
private HdmiPortInfo[] mHdmiPortInfo;
private ArrayList<Integer> mLocalDeviceTypes = new ArrayList<>();
private static final int PORT_ID_EARC_SUPPORTED = 3;
+ private static final int EARC_TRIGGER_START_ARC_ACTION_DELAY = 500;
@Before
public void setUp() throws Exception {
@@ -408,6 +409,60 @@
}
@Test
+ public void setRcProfileRootMenu_reportFeatureBroadcast() {
+ setRcProfileSourceDeviceTestHelper(
+ HdmiControlManager.CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_ROOT_MENU,
+ HdmiControlManager.RC_PROFILE_SOURCE_MENU_HANDLED);
+ }
+
+ @Test
+ public void setRcProfileSetupMenu_reportFeatureBroadcast() {
+ setRcProfileSourceDeviceTestHelper(
+ HdmiControlManager.CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_SETUP_MENU,
+ HdmiControlManager.RC_PROFILE_SOURCE_MENU_HANDLED);
+ }
+
+ @Test
+ public void setRcProfileContentMenu_reportFeatureBroadcast() {
+ setRcProfileSourceDeviceTestHelper(
+ HdmiControlManager.CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_CONTENTS_MENU,
+ HdmiControlManager.RC_PROFILE_SOURCE_MENU_HANDLED);
+ }
+
+ @Test
+ public void setRcProfileTopMenu_reportFeatureBroadcast() {
+ setRcProfileSourceDeviceTestHelper(
+ HdmiControlManager.CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_TOP_MENU,
+ HdmiControlManager.RC_PROFILE_SOURCE_MENU_HANDLED);
+ }
+
+ @Test
+ public void setRcProfileMediaSensitiveMenu_reportFeatureBroadcast() {
+ setRcProfileSourceDeviceTestHelper(
+ HdmiControlManager
+ .CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_MEDIA_CONTEXT_SENSITIVE_MENU,
+ HdmiControlManager.RC_PROFILE_SOURCE_MENU_HANDLED);
+ }
+
+ /** Helper method to test if feature discovery message sent given RCProfile change */
+ private void setRcProfileSourceDeviceTestHelper(final String setting, final int val) {
+ mNativeWrapper.clearResultMessages();
+
+ mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue(
+ HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION,
+ HdmiControlManager.HDMI_CEC_VERSION_2_0);
+ mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue(setting, val);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage reportFeatures = ReportFeaturesMessage.build(Constants.ADDR_PLAYBACK_1,
+ HdmiControlManager.HDMI_CEC_VERSION_2_0,
+ Arrays.asList(DEVICE_PLAYBACK, DEVICE_AUDIO_SYSTEM),
+ mPlaybackDeviceSpy.getRcProfile(), mPlaybackDeviceSpy.getRcFeatures(),
+ mPlaybackDeviceSpy.getDeviceFeatures());
+ assertThat(mNativeWrapper.getResultMessages()).contains(reportFeatures);
+ }
+
+ @Test
public void disableAndReenableCec_volumeControlReturnsToOriginalValue_enabled() {
int volumeControlEnabled = HdmiControlManager.VOLUME_CONTROL_ENABLED;
mHdmiControlServiceSpy.setHdmiCecVolumeControlEnabledInternal(volumeControlEnabled);
@@ -1320,6 +1375,11 @@
PORT_ID_EARC_SUPPORTED);
verify(mHdmiControlServiceSpy, times(1))
.notifyEarcStatusToAudioService(eq(false), eq(new ArrayList<>()));
+ // ARC should be never initiated here. It should be started after 500 ms.
+ verify(mHdmiControlServiceSpy, times(0)).startArcAction(anyBoolean(), any());
+ // We move 500 ms forward because the action is only started 500 ms later.
+ mTestLooper.moveTimeForward(EARC_TRIGGER_START_ARC_ACTION_DELAY);
+ mTestLooper.dispatchAll();
verify(mHdmiControlServiceSpy, times(1)).startArcAction(eq(true), any());
}
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTvTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTvTest.java
index 920c376..eed9975 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTvTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTvTest.java
@@ -16,11 +16,14 @@
package com.android.server.hdmi;
+import static android.hardware.hdmi.HdmiDeviceInfo.DEVICE_TV;
+
import static com.android.server.SystemService.PHASE_SYSTEM_SERVICES_READY;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
+import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.HdmiDeviceInfo;
import android.os.Looper;
import android.os.test.TestLooper;
@@ -35,6 +38,7 @@
import org.junit.runners.JUnit4;
import java.util.Collections;
+import java.util.List;
/**
* TV specific tests for {@link HdmiControlService} class.
@@ -47,6 +51,7 @@
private static final String TAG = "HdmiControlServiceTvTest";
private HdmiControlService mHdmiControlService;
private HdmiCecController mHdmiCecController;
+ private HdmiCecLocalDeviceTv mHdmiCecLocalDeviceTv;
private FakeNativeWrapper mNativeWrapper;
private HdmiEarcController mHdmiEarcController;
private FakeEarcNativeWrapper mEarcNativeWrapper;
@@ -90,6 +95,8 @@
mHdmiControlService.initService();
mTestLooper.dispatchAll();
+
+ mHdmiCecLocalDeviceTv = mHdmiControlService.tv();
}
@Test
@@ -139,4 +146,23 @@
assertThat(mHdmiControlService
.verifyPhysicalAddresses(HdmiUtils.buildMessage("4F:82:10"))).isFalse();
}
+
+ @Test
+ public void setRcProfileTv_reportFeatureBroadcast() {
+ mNativeWrapper.clearResultMessages();
+
+ mHdmiControlService.getHdmiCecConfig().setIntValue(
+ HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION,
+ HdmiControlManager.HDMI_CEC_VERSION_2_0);
+ mHdmiControlService.getHdmiCecConfig().setIntValue(
+ HdmiControlManager.CEC_SETTING_NAME_RC_PROFILE_TV,
+ HdmiControlManager.RC_PROFILE_TV_NONE);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage reportFeatures = ReportFeaturesMessage.build(Constants.ADDR_TV,
+ HdmiControlManager.HDMI_CEC_VERSION_2_0, List.of(DEVICE_TV),
+ mHdmiCecLocalDeviceTv.getRcProfile(), mHdmiCecLocalDeviceTv.getRcFeatures(),
+ mHdmiCecLocalDeviceTv.getDeviceFeatures());
+ assertThat(mNativeWrapper.getResultMessages()).contains(reportFeatures);
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/SystemAudioInitiationActionFromAvrTest.java b/services/tests/servicestests/src/com/android/server/hdmi/SystemAudioInitiationActionFromAvrTest.java
index f801f88..df27e78 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/SystemAudioInitiationActionFromAvrTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/SystemAudioInitiationActionFromAvrTest.java
@@ -15,6 +15,8 @@
*/
package com.android.server.hdmi;
+import static com.android.server.hdmi.HdmiConfig.TIMEOUT_MS;
+
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertFalse;
@@ -60,6 +62,7 @@
private boolean mArcEnabled;
private boolean mIsPlaybackDevice;
private boolean mBroadcastActiveSource;
+ private boolean mStandbyMessageReceived;
@Before
public void SetUp() {
@@ -135,6 +138,11 @@
int pathToPortId(int path) {
return -1;
}
+
+ @Override
+ protected boolean isStandbyMessageReceived() {
+ return mStandbyMessageReceived;
+ }
};
Looper looper = mTestLooper.getLooper();
@@ -286,6 +294,22 @@
assertThat(mHdmiCecLocalDeviceAudioSystem.isSystemAudioActivated()).isTrue();
}
+ @Test
+ public void onActionStarted_deviceGoesToSleep_noActiveSourceAfterTimeout() {
+ resetTestVariables();
+
+ mStandbyMessageReceived = true;
+ mHdmiCecLocalDeviceAudioSystem.addAndStartAction(
+ new SystemAudioInitiationActionFromAvr(
+ mHdmiCecLocalDeviceAudioSystem));
+ mTestLooper.dispatchAll();
+
+ mTestLooper.moveTimeForward(TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+
+ assertThat(mBroadcastActiveSource).isFalse();
+ }
+
private void resetTestVariables() {
mMsgRequestActiveSourceCount = 0;
mMsgSetSystemAudioModeCount = 0;
@@ -295,5 +319,6 @@
mBroadcastActiveSource = false;
mHdmiCecLocalDeviceAudioSystem.getActiveSource().physicalAddress =
Constants.INVALID_PHYSICAL_ADDRESS;
+ mStandbyMessageReceived = false;
}
}
diff --git a/services/tests/servicestests/src/com/android/server/power/hint/HintManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/hint/HintManagerServiceTest.java
index 5902caa..d0acacc 100644
--- a/services/tests/servicestests/src/com/android/server/power/hint/HintManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/hint/HintManagerServiceTest.java
@@ -26,12 +26,15 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyBoolean;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.anyLong;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
@@ -39,9 +42,12 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.annotation.NonNull;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.content.Context;
+import android.hardware.power.ChannelConfig;
+import android.hardware.power.IPower;
import android.hardware.power.SessionConfig;
import android.hardware.power.SessionTag;
import android.hardware.power.WorkDuration;
@@ -50,6 +56,7 @@
import android.os.IHintSession;
import android.os.PerformanceHintManager;
import android.os.Process;
+import android.os.RemoteException;
import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
@@ -130,12 +137,15 @@
@Mock
private HintManagerService.NativeWrapper mNativeWrapperMock;
@Mock
+ private IPower mIPowerMock;
+ @Mock
private ActivityManagerInternal mAmInternalMock;
@Rule
public final CheckFlagsRule mCheckFlagsRule =
DeviceFlagsValueProvider.createCheckFlagsRule();
private HintManagerService mService;
+ private ChannelConfig mConfig;
private static Answer<Long> fakeCreateWithConfig(Long ptr, Long sessionId) {
return new Answer<Long>() {
@@ -149,6 +159,9 @@
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
+ mConfig = new ChannelConfig();
+ mConfig.readFlagBitmask = 1;
+ mConfig.writeFlagBitmask = 2;
when(mNativeWrapperMock.halGetHintSessionPreferredRate())
.thenReturn(DEFAULT_HINT_PREFERRED_RATE);
when(mNativeWrapperMock.halCreateHintSession(eq(TGID), eq(UID), eq(SESSION_TIDS_A),
@@ -170,6 +183,8 @@
any(SessionConfig.class))).thenAnswer(fakeCreateWithConfig(SESSION_PTRS[2],
SESSION_IDS[2]));
+ when(mIPowerMock.getInterfaceVersion()).thenReturn(5);
+ when(mIPowerMock.getSessionChannel(anyInt(), anyInt())).thenReturn(mConfig);
LocalServices.removeServiceForTest(ActivityManagerInternal.class);
LocalServices.addService(ActivityManagerInternal.class, mAmInternalMock);
}
@@ -252,6 +267,9 @@
NativeWrapper createNativeWrapper() {
return mNativeWrapperMock;
}
+ IPower createIPower() {
+ return mIPowerMock;
+ }
});
return mService;
}
@@ -261,6 +279,9 @@
NativeWrapper createNativeWrapper() {
return new NativeWrapperFake();
}
+ IPower createIPower() {
+ return mIPowerMock;
+ }
});
return mService;
}
@@ -728,6 +749,102 @@
verify(mNativeWrapperMock, never()).halSetMode(anyLong(), anyInt(), anyBoolean());
}
+ @Test
+ public void testGetChannel() throws Exception {
+ HintManagerService service = createService();
+ Binder token = new Binder();
+
+ // Should only call once, after caching the first call
+ ChannelConfig config = service.getBinderServiceInstance().getSessionChannel(token);
+ ChannelConfig config2 = service.getBinderServiceInstance().getSessionChannel(token);
+ verify(mIPowerMock, times(1)).getSessionChannel(eq(TGID), eq(UID));
+ assertEquals(config.readFlagBitmask, mConfig.readFlagBitmask);
+ assertEquals(config.writeFlagBitmask, mConfig.writeFlagBitmask);
+ assertEquals(config2.readFlagBitmask, mConfig.readFlagBitmask);
+ assertEquals(config2.writeFlagBitmask, mConfig.writeFlagBitmask);
+ }
+
+ @Test
+ public void testGetChannelTwice() throws Exception {
+ HintManagerService service = createService();
+ Binder token = new Binder();
+
+ service.getBinderServiceInstance().getSessionChannel(token);
+ verify(mIPowerMock, times(1)).getSessionChannel(eq(TGID), eq(UID));
+ service.getBinderServiceInstance().closeSessionChannel();
+ verify(mIPowerMock, times(1)).closeSessionChannel(eq(TGID), eq(UID));
+
+ clearInvocations(mIPowerMock);
+
+ service.getBinderServiceInstance().getSessionChannel(token);
+ verify(mIPowerMock, times(1)).getSessionChannel(eq(TGID), eq(UID));
+ service.getBinderServiceInstance().closeSessionChannel();
+ verify(mIPowerMock, times(1)).closeSessionChannel(eq(TGID), eq(UID));
+ }
+
+ @Test
+ public void testGetChannelFails() throws Exception {
+ HintManagerService service = createService();
+ Binder token = new Binder();
+
+ when(mIPowerMock.getSessionChannel(anyInt(), anyInt())).thenThrow(RemoteException.class);
+
+ assertThrows(IllegalStateException.class, () -> {
+ service.getBinderServiceInstance().getSessionChannel(token);
+ });
+ }
+
+
+ @Test
+ public void testGetChannelBadVersion() throws Exception {
+ when(mIPowerMock.getInterfaceVersion()).thenReturn(3);
+ HintManagerService service = createService();
+ Binder token = new Binder();
+
+ reset(mIPowerMock);
+ when(mIPowerMock.getInterfaceVersion()).thenReturn(3);
+ when(mIPowerMock.getSessionChannel(anyInt(), anyInt())).thenReturn(mConfig);
+
+ ChannelConfig channel = service.getBinderServiceInstance().getSessionChannel(token);
+ verify(mIPowerMock, times(0)).getSessionChannel(eq(TGID), eq(UID));
+ assertNull(channel);
+ }
+
+ @Test
+ public void testCloseChannel() throws Exception {
+ HintManagerService service = createService();
+ Binder token = new Binder();
+
+ service.getBinderServiceInstance().getSessionChannel(token);
+ service.getBinderServiceInstance().closeSessionChannel();
+ verify(mIPowerMock, times(1)).closeSessionChannel(eq(TGID), eq(UID));
+ }
+
+ @Test
+ public void testCloseChannelFails() throws Exception {
+ HintManagerService service = createService();
+ Binder token = new Binder();
+
+ service.getBinderServiceInstance().getSessionChannel(token);
+
+ doThrow(RemoteException.class).when(mIPowerMock).closeSessionChannel(anyInt(), anyInt());
+
+ assertThrows(IllegalStateException.class, () -> {
+ service.getBinderServiceInstance().closeSessionChannel();
+ });
+ }
+
+ @Test
+ public void testDoubleClose() throws Exception {
+ HintManagerService service = createService();
+ Binder token = new Binder();
+
+ service.getBinderServiceInstance().getSessionChannel(token);
+ service.getBinderServiceInstance().closeSessionChannel();
+ service.getBinderServiceInstance().closeSessionChannel();
+ verify(mIPowerMock, times(1)).closeSessionChannel(eq(TGID), eq(UID));
+ }
+
// This test checks that concurrent operations from different threads on IHintService,
// IHintSession and UidObserver will not cause data race or deadlock. Ideally we should also
// check the output of threads' reportActualDuration performance to detect lock starvation
@@ -935,4 +1052,40 @@
a.reportActualWorkDuration2(WORK_DURATIONS_FIVE);
verify(mNativeWrapperMock, never()).halReportActualWorkDuration(anyLong(), any(), any());
}
+
+ @Test
+ public void testChannelDiesWhenTokenDies() throws Exception {
+ HintManagerService service = createService();
+
+ class DyingToken extends Binder {
+ DeathRecipient mToNotify;
+ @Override
+ public void linkToDeath(@NonNull DeathRecipient recipient, int flags) {
+ mToNotify = recipient;
+ super.linkToDeath(recipient, flags);
+ }
+
+ public void fakeDeath() {
+ mToNotify.binderDied();
+ }
+ }
+
+ DyingToken token = new DyingToken();
+
+ service.getBinderServiceInstance().getSessionChannel(token);
+ verify(mIPowerMock, times(1)).getSessionChannel(eq(TGID), eq(UID));
+ assertTrue(service.hasChannel(TGID, UID));
+
+ token.fakeDeath();
+
+ assertFalse(service.hasChannel(TGID, UID));
+ verify(mIPowerMock, times(1)).closeSessionChannel(eq(TGID), eq(UID));
+
+ clearInvocations(mIPowerMock);
+
+ token = new DyingToken();
+ service.getBinderServiceInstance().getSessionChannel(token);
+ verify(mIPowerMock, times(1)).getSessionChannel(eq(TGID), eq(UID));
+ assertTrue(service.hasChannel(TGID, UID));
+ }
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/GroupHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/GroupHelperTest.java
index 1194973..c7c97e4 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/GroupHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/GroupHelperTest.java
@@ -34,6 +34,7 @@
import static junit.framework.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
@@ -54,6 +55,7 @@
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.os.UserHandle;
+import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.service.notification.StatusBarNotification;
@@ -271,7 +273,8 @@
}
@Test
- public void testAddSummary() {
+ @DisableFlags(android.app.Flags.FLAG_CHECK_AUTOGROUP_BEFORE_POST)
+ public void testAddSummary_alwaysAutogroup() {
final String pkg = "package";
for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) {
mGroupHelper.onNotificationPosted(
@@ -279,13 +282,52 @@
}
verify(mCallback, times(1)).addAutoGroupSummary(
anyInt(), eq(pkg), anyString(), eq(getNotificationAttributes(BASE_FLAGS)));
- verify(mCallback, times(AUTOGROUP_AT_COUNT)).addAutoGroup(anyString());
+ verify(mCallback, times(AUTOGROUP_AT_COUNT)).addAutoGroup(anyString(), anyBoolean());
verify(mCallback, never()).removeAutoGroup(anyString());
verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString());
verify(mCallback, never()).updateAutogroupSummary(anyInt(), anyString(), any());
}
@Test
+ @EnableFlags(android.app.Flags.FLAG_CHECK_AUTOGROUP_BEFORE_POST)
+ public void testAddSummary() {
+ final String pkg = "package";
+ for (int i = 0; i < AUTOGROUP_AT_COUNT - 1; i++) {
+ assertThat(mGroupHelper.onNotificationPosted(
+ getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM), false)).isFalse();
+ }
+ assertThat(mGroupHelper.onNotificationPosted(
+ getSbn(pkg, AUTOGROUP_AT_COUNT - 1, String.valueOf(AUTOGROUP_AT_COUNT - 1),
+ UserHandle.SYSTEM), false)).isTrue();
+ verify(mCallback, times(1)).addAutoGroupSummary(
+ anyInt(), eq(pkg), anyString(), eq(getNotificationAttributes(BASE_FLAGS)));
+ verify(mCallback, times(AUTOGROUP_AT_COUNT - 1)).addAutoGroup(anyString(), anyBoolean());
+ verify(mCallback, never()).removeAutoGroup(anyString());
+ verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString());
+ verify(mCallback, never()).updateAutogroupSummary(anyInt(), anyString(), any());
+ }
+
+ @Test
+ @DisableFlags(android.app.Flags.FLAG_CHECK_AUTOGROUP_BEFORE_POST)
+ public void testAddSummary_oneChildOngoing_summaryOngoing_alwaysAutogroup() {
+ final String pkg = "package";
+ for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) {
+ StatusBarNotification sbn = getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM);
+ if (i == 0) {
+ sbn.getNotification().flags |= FLAG_ONGOING_EVENT;
+ }
+ mGroupHelper.onNotificationPosted(sbn, false);
+ }
+ verify(mCallback, times(1)).addAutoGroupSummary(anyInt(), eq(pkg), anyString(),
+ eq(getNotificationAttributes(BASE_FLAGS | FLAG_ONGOING_EVENT)));
+ verify(mCallback, times(AUTOGROUP_AT_COUNT)).addAutoGroup(anyString(), anyBoolean());
+ verify(mCallback, never()).removeAutoGroup(anyString());
+ verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString());
+ verify(mCallback, never()).updateAutogroupSummary(anyInt(), anyString(), any());
+ }
+
+ @Test
+ @EnableFlags(android.app.Flags.FLAG_CHECK_AUTOGROUP_BEFORE_POST)
public void testAddSummary_oneChildOngoing_summaryOngoing() {
final String pkg = "package";
for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) {
@@ -297,13 +339,33 @@
}
verify(mCallback, times(1)).addAutoGroupSummary(anyInt(), eq(pkg), anyString(),
eq(getNotificationAttributes(BASE_FLAGS | FLAG_ONGOING_EVENT)));
- verify(mCallback, times(AUTOGROUP_AT_COUNT)).addAutoGroup(anyString());
+ verify(mCallback, times(AUTOGROUP_AT_COUNT - 1)).addAutoGroup(anyString(), anyBoolean());
verify(mCallback, never()).removeAutoGroup(anyString());
verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString());
verify(mCallback, never()).updateAutogroupSummary(anyInt(), anyString(), any());
}
@Test
+ @DisableFlags(android.app.Flags.FLAG_CHECK_AUTOGROUP_BEFORE_POST)
+ public void testAddSummary_oneChildAutoCancel_summaryNotAutoCancel_alwaysAutogroup() {
+ final String pkg = "package";
+ for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) {
+ StatusBarNotification sbn = getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM);
+ if (i == 0) {
+ sbn.getNotification().flags |= FLAG_AUTO_CANCEL;
+ }
+ mGroupHelper.onNotificationPosted(sbn, false);
+ }
+ verify(mCallback, times(1)).addAutoGroupSummary(
+ anyInt(), eq(pkg), anyString(), eq(getNotificationAttributes(BASE_FLAGS)));
+ verify(mCallback, times(AUTOGROUP_AT_COUNT)).addAutoGroup(anyString(), anyBoolean());
+ verify(mCallback, never()).removeAutoGroup(anyString());
+ verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString());
+ verify(mCallback, never()).updateAutogroupSummary(anyInt(), anyString(), any());
+ }
+
+ @Test
+ @EnableFlags(android.app.Flags.FLAG_CHECK_AUTOGROUP_BEFORE_POST)
public void testAddSummary_oneChildAutoCancel_summaryNotAutoCancel() {
final String pkg = "package";
for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) {
@@ -315,13 +377,31 @@
}
verify(mCallback, times(1)).addAutoGroupSummary(
anyInt(), eq(pkg), anyString(), eq(getNotificationAttributes(BASE_FLAGS)));
- verify(mCallback, times(AUTOGROUP_AT_COUNT)).addAutoGroup(anyString());
+ verify(mCallback, times(AUTOGROUP_AT_COUNT - 1)).addAutoGroup(anyString(), anyBoolean());
verify(mCallback, never()).removeAutoGroup(anyString());
verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString());
verify(mCallback, never()).updateAutogroupSummary(anyInt(), anyString(), any());
}
@Test
+ @DisableFlags(android.app.Flags.FLAG_CHECK_AUTOGROUP_BEFORE_POST)
+ public void testAddSummary_allChildrenAutoCancel_summaryAutoCancel_alwaysAutogroup() {
+ final String pkg = "package";
+ for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) {
+ StatusBarNotification sbn = getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM);
+ sbn.getNotification().flags |= FLAG_AUTO_CANCEL;
+ mGroupHelper.onNotificationPosted(sbn, false);
+ }
+ verify(mCallback, times(1)).addAutoGroupSummary(anyInt(), eq(pkg), anyString(),
+ eq(getNotificationAttributes(BASE_FLAGS | FLAG_AUTO_CANCEL)));
+ verify(mCallback, times(AUTOGROUP_AT_COUNT)).addAutoGroup(anyString(), anyBoolean());
+ verify(mCallback, never()).removeAutoGroup(anyString());
+ verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString());
+ verify(mCallback, never()).updateAutogroupSummary(anyInt(), anyString(), any());
+ }
+
+ @Test
+ @EnableFlags(android.app.Flags.FLAG_CHECK_AUTOGROUP_BEFORE_POST)
public void testAddSummary_allChildrenAutoCancel_summaryAutoCancel() {
final String pkg = "package";
for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) {
@@ -331,13 +411,34 @@
}
verify(mCallback, times(1)).addAutoGroupSummary(anyInt(), eq(pkg), anyString(),
eq(getNotificationAttributes(BASE_FLAGS | FLAG_AUTO_CANCEL)));
- verify(mCallback, times(AUTOGROUP_AT_COUNT)).addAutoGroup(anyString());
+ verify(mCallback, times(AUTOGROUP_AT_COUNT - 1)).addAutoGroup(anyString(), anyBoolean());
verify(mCallback, never()).removeAutoGroup(anyString());
verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString());
verify(mCallback, never()).updateAutogroupSummary(anyInt(), anyString(), any());
}
@Test
+ @DisableFlags(android.app.Flags.FLAG_CHECK_AUTOGROUP_BEFORE_POST)
+ public void testAddSummary_summaryAutoCancelNoClear_alwaysAutogroup() {
+ final String pkg = "package";
+ for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) {
+ StatusBarNotification sbn = getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM);
+ sbn.getNotification().flags |= FLAG_AUTO_CANCEL;
+ if (i == 0) {
+ sbn.getNotification().flags |= FLAG_NO_CLEAR;
+ }
+ mGroupHelper.onNotificationPosted(sbn, false);
+ }
+ verify(mCallback, times(1)).addAutoGroupSummary(anyInt(), eq(pkg), anyString(),
+ eq(getNotificationAttributes(BASE_FLAGS | FLAG_AUTO_CANCEL | FLAG_NO_CLEAR)));
+ verify(mCallback, times(AUTOGROUP_AT_COUNT)).addAutoGroup(anyString(), anyBoolean());
+ verify(mCallback, never()).removeAutoGroup(anyString());
+ verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString());
+ verify(mCallback, never()).updateAutogroupSummary(anyInt(), anyString(), any());
+ }
+
+ @Test
+ @EnableFlags(android.app.Flags.FLAG_CHECK_AUTOGROUP_BEFORE_POST)
public void testAddSummary_summaryAutoCancelNoClear() {
final String pkg = "package";
for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) {
@@ -350,7 +451,7 @@
}
verify(mCallback, times(1)).addAutoGroupSummary(anyInt(), eq(pkg), anyString(),
eq(getNotificationAttributes(BASE_FLAGS | FLAG_AUTO_CANCEL | FLAG_NO_CLEAR)));
- verify(mCallback, times(AUTOGROUP_AT_COUNT)).addAutoGroup(anyString());
+ verify(mCallback, times(AUTOGROUP_AT_COUNT - 1)).addAutoGroup(anyString(), anyBoolean());
verify(mCallback, never()).removeAutoGroup(anyString());
verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString());
verify(mCallback, never()).updateAutogroupSummary(anyInt(), anyString(), any());
@@ -617,7 +718,7 @@
}
verify(mCallback, times(1)).addAutoGroupSummary(
anyInt(), eq(pkg), anyString(), eq(getNotificationAttributes(BASE_FLAGS)));
- verify(mCallback, times(AUTOGROUP_AT_COUNT)).addAutoGroup(anyString());
+ verify(mCallback, times(AUTOGROUP_AT_COUNT)).addAutoGroup(anyString(), anyBoolean());
verify(mCallback, never()).removeAutoGroup(anyString());
verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString());
Mockito.reset(mCallback);
@@ -645,7 +746,7 @@
}
verify(mCallback, times(1)).addAutoGroupSummary(
anyInt(), eq(pkg), anyString(), eq(getNotificationAttributes(BASE_FLAGS)));
- verify(mCallback, times(AUTOGROUP_AT_COUNT)).addAutoGroup(anyString());
+ verify(mCallback, times(AUTOGROUP_AT_COUNT)).addAutoGroup(anyString(), anyBoolean());
verify(mCallback, never()).removeAutoGroup(anyString());
verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString());
Mockito.reset(mCallback);
@@ -664,7 +765,8 @@
}
@Test
- public void testNewNotificationsAddedToAutogroup_ifOriginalNotificationsCanceled() {
+ @DisableFlags(android.app.Flags.FLAG_CHECK_AUTOGROUP_BEFORE_POST)
+ public void testNewNotificationsAddedToAutogroup_ifOriginalNotificationsCanceled_alwaysGroup() {
final String pkg = "package";
List<StatusBarNotification> posted = new ArrayList<>();
for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) {
@@ -674,7 +776,7 @@
}
verify(mCallback, times(1)).addAutoGroupSummary(
anyInt(), eq(pkg), anyString(), eq(getNotificationAttributes(BASE_FLAGS)));
- verify(mCallback, times(AUTOGROUP_AT_COUNT)).addAutoGroup(anyString());
+ verify(mCallback, times(AUTOGROUP_AT_COUNT)).addAutoGroup(anyString(), anyBoolean());
verify(mCallback, never()).removeAutoGroup(anyString());
verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString());
Mockito.reset(mCallback);
@@ -693,8 +795,8 @@
// < AUTOGROUP_AT_COUNT
final StatusBarNotification sbn = getSbn(pkg, 5, String.valueOf(5), UserHandle.SYSTEM);
posted.add(sbn);
- mGroupHelper.onNotificationPosted(sbn, true);
- verify(mCallback, times(1)).addAutoGroup(sbn.getKey());
+ assertThat(mGroupHelper.onNotificationPosted(sbn, true)).isFalse();
+ verify(mCallback, times(1)).addAutoGroup(sbn.getKey(), true);
verify(mCallback, never()).removeAutoGroup(anyString());
verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString());
verify(mCallback).updateAutogroupSummary(anyInt(), anyString(),
@@ -703,7 +805,84 @@
}
@Test
+ @EnableFlags(android.app.Flags.FLAG_CHECK_AUTOGROUP_BEFORE_POST)
+ public void testNewNotificationsAddedToAutogroup_ifOriginalNotificationsCanceled() {
+ final String pkg = "package";
+ List<StatusBarNotification> posted = new ArrayList<>();
+ for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) {
+ final StatusBarNotification sbn = getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM);
+ posted.add(sbn);
+ mGroupHelper.onNotificationPosted(sbn, false);
+ }
+
+ verify(mCallback, times(1)).addAutoGroupSummary(
+ anyInt(), eq(pkg), anyString(), eq(getNotificationAttributes(BASE_FLAGS)));
+ verify(mCallback, times(AUTOGROUP_AT_COUNT - 1)).addAutoGroup(anyString(), anyBoolean());
+ verify(mCallback, never()).removeAutoGroup(anyString());
+ verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString());
+ Mockito.reset(mCallback);
+
+ for (int i = posted.size() - 2; i >= 0; i--) {
+ mGroupHelper.onNotificationRemoved(posted.remove(i));
+ }
+ verify(mCallback, never()).removeAutoGroup(anyString());
+ verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString());
+ Mockito.reset(mCallback);
+
+ // only one child remains
+ assertEquals(1, mGroupHelper.getNotGroupedByAppCount(UserHandle.USER_SYSTEM, pkg));
+
+ // Add new notification; it should be autogrouped even though the total count is
+ // < AUTOGROUP_AT_COUNT
+ final StatusBarNotification sbn = getSbn(pkg, 5, String.valueOf(5), UserHandle.SYSTEM);
+ posted.add(sbn);
+ assertThat(mGroupHelper.onNotificationPosted(sbn, true)).isTrue();
+ // addAutoGroup not called on sbn, because the autogrouping is expected to be done
+ // synchronously.
+ verify(mCallback, never()).removeAutoGroup(anyString());
+ verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString());
+ verify(mCallback).updateAutogroupSummary(anyInt(), anyString(),
+ eq(getNotificationAttributes(BASE_FLAGS)));
+ verify(mCallback, never()).addAutoGroupSummary(anyInt(), anyString(), anyString(), any());
+ }
+
+ @Test
+ @DisableFlags(android.app.Flags.FLAG_CHECK_AUTOGROUP_BEFORE_POST)
@EnableFlags(Flags.FLAG_AUTOGROUP_SUMMARY_ICON_UPDATE)
+ public void testAddSummary_sameIcon_sameColor_alwaysAutogroup() {
+ final String pkg = "package";
+ final Icon icon = mock(Icon.class);
+ when(icon.sameAs(icon)).thenReturn(true);
+ final int iconColor = Color.BLUE;
+ final NotificationAttributes attr = new NotificationAttributes(BASE_FLAGS, icon, iconColor,
+ DEFAULT_VISIBILITY);
+
+ // Add notifications with same icon and color
+ for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) {
+ StatusBarNotification sbn = getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM, null,
+ icon, iconColor);
+ mGroupHelper.onNotificationPosted(sbn, false);
+ }
+ // Check that the summary would have the same icon and color
+ verify(mCallback, times(1)).addAutoGroupSummary(
+ anyInt(), eq(pkg), anyString(), eq(attr));
+ verify(mCallback, times(AUTOGROUP_AT_COUNT)).addAutoGroup(anyString(), anyBoolean());
+ verify(mCallback, never()).removeAutoGroup(anyString());
+ verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString());
+
+ // After auto-grouping, add new notification with the same color
+ StatusBarNotification sbn = getSbn(pkg, AUTOGROUP_AT_COUNT,
+ String.valueOf(AUTOGROUP_AT_COUNT), UserHandle.SYSTEM, null, icon, iconColor);
+ mGroupHelper.onNotificationPosted(sbn, true);
+
+ // Check that the summary was updated
+ //NotificationAttributes newAttr = new NotificationAttributes(BASE_FLAGS, icon, iconColor);
+ verify(mCallback, times(1)).updateAutogroupSummary(anyInt(), anyString(), eq(attr));
+ }
+
+ @Test
+ @EnableFlags({Flags.FLAG_AUTOGROUP_SUMMARY_ICON_UPDATE,
+ android.app.Flags.FLAG_CHECK_AUTOGROUP_BEFORE_POST})
public void testAddSummary_sameIcon_sameColor() {
final String pkg = "package";
final Icon icon = mock(Icon.class);
@@ -721,7 +900,7 @@
// Check that the summary would have the same icon and color
verify(mCallback, times(1)).addAutoGroupSummary(
anyInt(), eq(pkg), anyString(), eq(attr));
- verify(mCallback, times(AUTOGROUP_AT_COUNT)).addAutoGroup(anyString());
+ verify(mCallback, times(AUTOGROUP_AT_COUNT - 1)).addAutoGroup(anyString(), anyBoolean());
verify(mCallback, never()).removeAutoGroup(anyString());
verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString());
@@ -761,7 +940,7 @@
// Check that the summary would have the same icon and color
verify(mCallback, times(1)).addAutoGroupSummary(
anyInt(), eq(pkg), anyString(), eq(initialAttr));
- verify(mCallback, times(AUTOGROUP_AT_COUNT)).addAutoGroup(anyString());
+ verify(mCallback, times(AUTOGROUP_AT_COUNT)).addAutoGroup(anyString(), anyBoolean());
verify(mCallback, never()).removeAutoGroup(anyString());
verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString());
@@ -780,8 +959,9 @@
}
@Test
+ @DisableFlags(android.app.Flags.FLAG_CHECK_AUTOGROUP_BEFORE_POST)
@EnableFlags(Flags.FLAG_AUTOGROUP_SUMMARY_ICON_UPDATE)
- public void testAddSummary_diffVisibility() {
+ public void testAddSummary_diffVisibility_alwaysAutogroup() {
final String pkg = "package";
final Icon icon = mock(Icon.class);
when(icon.sameAs(icon)).thenReturn(true);
@@ -798,7 +978,8 @@
// Check that the summary has private visibility
verify(mCallback, times(1)).addAutoGroupSummary(
anyInt(), eq(pkg), anyString(), eq(attr));
- verify(mCallback, times(AUTOGROUP_AT_COUNT)).addAutoGroup(anyString());
+
+ verify(mCallback, times(AUTOGROUP_AT_COUNT)).addAutoGroup(anyString(), anyBoolean());
verify(mCallback, never()).removeAutoGroup(anyString());
verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString());
@@ -815,6 +996,48 @@
}
@Test
+ @EnableFlags({Flags.FLAG_AUTOGROUP_SUMMARY_ICON_UPDATE,
+ android.app.Flags.FLAG_CHECK_AUTOGROUP_BEFORE_POST})
+ public void testAddSummary_diffVisibility() {
+ final String pkg = "package";
+ final Icon icon = mock(Icon.class);
+ when(icon.sameAs(icon)).thenReturn(true);
+ final int iconColor = Color.BLUE;
+ final NotificationAttributes attr = new NotificationAttributes(BASE_FLAGS, icon, iconColor,
+ VISIBILITY_PRIVATE);
+
+ // Add notifications with same icon and color and default visibility (private)
+ for (int i = 0; i < AUTOGROUP_AT_COUNT - 1; i++) {
+ StatusBarNotification sbn = getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM, null,
+ icon, iconColor);
+ assertThat(mGroupHelper.onNotificationPosted(sbn, false)).isFalse();
+ }
+ // The last notification added will reach the autogroup threshold.
+ StatusBarNotification sbn = getSbn(pkg, AUTOGROUP_AT_COUNT - 1,
+ String.valueOf(AUTOGROUP_AT_COUNT - 1), UserHandle.SYSTEM, null, icon, iconColor);
+ assertThat(mGroupHelper.onNotificationPosted(sbn, false)).isTrue();
+
+ // Check that the summary has private visibility
+ verify(mCallback, times(1)).addAutoGroupSummary(
+ anyInt(), eq(pkg), anyString(), eq(attr));
+ // The last sbn is expected to be added to autogroup synchronously.
+ verify(mCallback, times(AUTOGROUP_AT_COUNT - 1)).addAutoGroup(anyString(), anyBoolean());
+ verify(mCallback, never()).removeAutoGroup(anyString());
+ verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString());
+
+ // After auto-grouping, add new notification with public visibility
+ sbn = getSbn(pkg, AUTOGROUP_AT_COUNT,
+ String.valueOf(AUTOGROUP_AT_COUNT), UserHandle.SYSTEM, null, icon, iconColor);
+ sbn.getNotification().visibility = VISIBILITY_PUBLIC;
+ assertThat(mGroupHelper.onNotificationPosted(sbn, true)).isTrue();
+
+ // Check that the summary visibility was updated
+ NotificationAttributes newAttr = new NotificationAttributes(BASE_FLAGS, icon, iconColor,
+ VISIBILITY_PUBLIC);
+ verify(mCallback, times(1)).updateAutogroupSummary(anyInt(), anyString(), eq(newAttr));
+ }
+
+ @Test
@EnableFlags(Flags.FLAG_AUTOGROUP_SUMMARY_ICON_UPDATE)
public void testAutoGrouped_diffIcon_diffColor_removeChild_updateTo_sameIcon_sameColor() {
final String pkg = "package";
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 3a0eba1..5e2fe6a 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -311,6 +311,7 @@
import com.google.android.collect.Lists;
import com.google.common.collect.ImmutableList;
+
import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
@@ -331,8 +332,6 @@
import org.mockito.MockitoAnnotations;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
-import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
-import platform.test.runner.parameterized.Parameters;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
@@ -342,12 +341,14 @@
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.function.Consumer;
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
+import platform.test.runner.parameterized.Parameters;
+
@SmallTest
@RunWith(ParameterizedAndroidJunit4.class)
@RunWithLooper
@@ -501,7 +502,7 @@
@Mock
MultiRateLimiter mToastRateLimiter;
BroadcastReceiver mPackageIntentReceiver;
- BroadcastReceiver mUserSwitchIntentReceiver;
+ BroadcastReceiver mUserIntentReceiver;
BroadcastReceiver mNotificationTimeoutReceiver;
NotificationRecordLoggerFake mNotificationRecordLogger = new NotificationRecordLoggerFake();
TestableNotificationManagerService.StrongAuthTrackerFake mStrongAuthTracker;
@@ -800,11 +801,13 @@
&& filter.hasAction(Intent.ACTION_PACKAGES_SUSPENDED)) {
mPackageIntentReceiver = broadcastReceivers.get(i);
}
- if (filter.hasAction(Intent.ACTION_USER_SWITCHED)) {
+ if (filter.hasAction(Intent.ACTION_USER_SWITCHED)
+ || filter.hasAction(Intent.ACTION_PROFILE_UNAVAILABLE)
+ || filter.hasAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE)) {
// There may be multiple receivers, get the NMS one
if (broadcastReceivers.get(i).toString().contains(
NotificationManagerService.class.getName())) {
- mUserSwitchIntentReceiver = broadcastReceivers.get(i);
+ mUserIntentReceiver = broadcastReceivers.get(i);
}
}
if (filter.hasAction(ACTION_NOTIFICATION_TIMEOUT)
@@ -813,7 +816,7 @@
}
}
assertNotNull("package intent receiver should exist", mPackageIntentReceiver);
- assertNotNull("User-switch receiver should exist", mUserSwitchIntentReceiver);
+ assertNotNull("User receiver should exist", mUserIntentReceiver);
if (!Flags.allNotifsNeedTtl()) {
assertNotNull("Notification timeout receiver should exist",
mNotificationTimeoutReceiver);
@@ -974,7 +977,7 @@
private void simulateProfileAvailabilityActions(String intentAction) {
final Intent intent = new Intent(intentAction);
intent.putExtra(Intent.EXTRA_USER_HANDLE, TEST_PROFILE_USERHANDLE);
- mUserSwitchIntentReceiver.onReceive(mContext, intent);
+ mUserIntentReceiver.onReceive(mContext, intent);
}
private ArrayMap<Boolean, ArrayList<ComponentName>> generateResetComponentValues() {
@@ -5542,7 +5545,7 @@
public void testAddAutogroup_requestsSort() throws Exception {
final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
mService.addNotification(r);
- mService.addAutogroupKeyLocked(r.getKey());
+ mService.addAutogroupKeyLocked(r.getKey(), true);
verify(mRankingHandler, times(1)).requestSort();
}
@@ -5562,12 +5565,30 @@
final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
r.setOverrideGroupKey("TEST");
mService.addNotification(r);
- mService.addAutogroupKeyLocked(r.getKey());
+ mService.addAutogroupKeyLocked(r.getKey(), true);
verify(mRankingHandler, never()).requestSort();
}
@Test
+ @EnableFlags(android.app.Flags.FLAG_CHECK_AUTOGROUP_BEFORE_POST)
+ public void testAutogroupSuppressSort_noSort() throws Exception {
+ final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
+ mService.addNotification(r);
+ mService.addAutogroupKeyLocked(r.getKey(), false);
+
+ verify(mRankingHandler, never()).requestSort();
+ }
+
+ @Test
+ @EnableFlags(android.app.Flags.FLAG_CHECK_AUTOGROUP_BEFORE_POST)
+ public void testAutogroupOnPost_skipManualSort() throws Exception {
+ final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
+ mService.addNotification(r);
+ verify(mRankingHandler, never()).requestSort();
+ }
+
+ @Test
public void testHandleRankingSort_sendsUpdateOnSignalExtractorChange() throws Exception {
mService.setPreferencesHelper(mPreferencesHelper);
NotificationManagerService.WorkerHandler handler = mock(
@@ -14462,13 +14483,33 @@
}
@Test
+ @EnableFlags(Flags.FLAG_USE_SSM_USER_SWITCH_SIGNAL)
public void onUserSwitched_updatesZenModeAndChannelsBypassingDnd() {
+ mService.mZenModeHelper = mock(ZenModeHelper.class);
+ mService.setPreferencesHelper(mPreferencesHelper);
+
+ UserInfo prevUser = new UserInfo();
+ prevUser.id = 10;
+ UserInfo newUser = new UserInfo();
+ newUser.id = 20;
+
+ mService.onUserSwitching(new TargetUser(prevUser), new TargetUser(newUser));
+
+ InOrder inOrder = inOrder(mPreferencesHelper, mService.mZenModeHelper);
+ inOrder.verify(mService.mZenModeHelper).onUserSwitched(eq(20));
+ inOrder.verify(mPreferencesHelper).syncChannelsBypassingDnd();
+ inOrder.verifyNoMoreInteractions();
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_USE_SSM_USER_SWITCH_SIGNAL)
+ public void onUserSwitched_broadcast_updatesZenModeAndChannelsBypassingDnd() {
Intent intent = new Intent(Intent.ACTION_USER_SWITCHED);
intent.putExtra(Intent.EXTRA_USER_HANDLE, 20);
mService.mZenModeHelper = mock(ZenModeHelper.class);
mService.setPreferencesHelper(mPreferencesHelper);
- mUserSwitchIntentReceiver.onReceive(mContext, intent);
+ mUserIntentReceiver.onReceive(mContext, intent);
InOrder inOrder = inOrder(mPreferencesHelper, mService.mZenModeHelper);
inOrder.verify(mService.mZenModeHelper).onUserSwitched(eq(20));
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
index 5fdb396..d1423fe 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -3002,39 +3002,45 @@
assertEquals(ZEN_MODE_OFF, mZenModeHelper.mZenMode);
}
- private enum ModesApiFlag {
- ENABLED(true, /* originForUserActionInSystemUi= */ UPDATE_ORIGIN_USER),
- DISABLED(false, /* originForUserActionInSystemUi= */ UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI);
+ private enum ModesFlag {
+ MODES_UI(2, /* originForUserActionInSystemUi= */ UPDATE_ORIGIN_USER),
+ MODES_API(1, /* originForUserActionInSystemUi= */ UPDATE_ORIGIN_USER),
+ DISABLED(0, /* originForUserActionInSystemUi= */ UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI);
- private final boolean mEnabled;
+ private final int mFlagsEnabled;
@ConfigChangeOrigin
private final int mOriginForUserActionInSystemUi;
- ModesApiFlag(boolean enabled, @ConfigChangeOrigin int originForUserActionInSystemUi) {
- this.mEnabled = enabled;
+ ModesFlag(int flagsEnabled, @ConfigChangeOrigin int originForUserActionInSystemUi) {
+ this.mFlagsEnabled = flagsEnabled;
this.mOriginForUserActionInSystemUi = originForUserActionInSystemUi;
}
- void applyFlag(SetFlagsRule setFlagsRule) {
- if (mEnabled) {
+ void applyFlags(SetFlagsRule setFlagsRule) {
+ if (mFlagsEnabled >= 1) {
setFlagsRule.enableFlags(Flags.FLAG_MODES_API);
} else {
setFlagsRule.disableFlags(Flags.FLAG_MODES_API);
}
+ if (mFlagsEnabled >= 2) {
+ setFlagsRule.enableFlags(Flags.FLAG_MODES_UI);
+ } else {
+ setFlagsRule.disableFlags(Flags.FLAG_MODES_UI);
+ }
}
}
@Test
- public void testZenModeEventLog_setManualZenMode(@TestParameter ModesApiFlag modesApiFlag)
+ public void testZenModeEventLog_setManualZenMode(@TestParameter ModesFlag modesFlag)
throws IllegalArgumentException {
- modesApiFlag.applyFlag(mSetFlagsRule);
+ modesFlag.applyFlags(mSetFlagsRule);
mTestFlagResolver.setFlagOverride(LOG_DND_STATE_EVENTS, true);
setupZenConfig();
// Turn zen mode on (to important_interruptions)
// Need to additionally call the looper in order to finish the post-apply-config process
mZenModeHelper.setManualZenMode(ZEN_MODE_IMPORTANT_INTERRUPTIONS, null,
- modesApiFlag.mOriginForUserActionInSystemUi, "", null, Process.SYSTEM_UID);
+ modesFlag.mOriginForUserActionInSystemUi, "", null, Process.SYSTEM_UID);
// Now turn zen mode off, but via a different package UID -- this should get registered as
// "not an action by the user" because some other app is changing zen mode
@@ -3062,7 +3068,7 @@
assertEquals(DNDProtoEnums.MANUAL_RULE, mZenModeEventLogger.getChangedRuleType(0));
assertEquals(1, mZenModeEventLogger.getNumRulesActive(0));
assertThat(mZenModeEventLogger.getFromSystemOrSystemUi(0)).isEqualTo(
- modesApiFlag == ModesApiFlag.DISABLED);
+ modesFlag == ModesFlag.DISABLED);
assertTrue(mZenModeEventLogger.getIsUserAction(0));
assertEquals(Process.SYSTEM_UID, mZenModeEventLogger.getPackageUid(0));
checkDndProtoMatchesSetupZenConfig(mZenModeEventLogger.getPolicyProto(0));
@@ -3091,9 +3097,9 @@
}
@Test
- public void testZenModeEventLog_automaticRules(@TestParameter ModesApiFlag modesApiFlag)
+ public void testZenModeEventLog_automaticRules(@TestParameter ModesFlag modesFlag)
throws IllegalArgumentException {
- modesApiFlag.applyFlag(mSetFlagsRule);
+ modesFlag.applyFlags(mSetFlagsRule);
mTestFlagResolver.setFlagOverride(LOG_DND_STATE_EVENTS, true);
setupZenConfig();
@@ -3116,7 +3122,7 @@
// Event 2: "User" turns off the automatic rule (sets it to not enabled)
zenRule.setEnabled(false);
mZenModeHelper.updateAutomaticZenRule(id, zenRule,
- modesApiFlag.mOriginForUserActionInSystemUi, "", Process.SYSTEM_UID);
+ modesFlag.mOriginForUserActionInSystemUi, "", Process.SYSTEM_UID);
// Add a new system rule
AutomaticZenRule systemRule = new AutomaticZenRule("systemRule",
@@ -3134,7 +3140,7 @@
UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID);
// Event 4: "User" deletes the rule
- mZenModeHelper.removeAutomaticZenRule(systemId, modesApiFlag.mOriginForUserActionInSystemUi,
+ mZenModeHelper.removeAutomaticZenRule(systemId, modesFlag.mOriginForUserActionInSystemUi,
"", Process.SYSTEM_UID);
// In total, this represents 4 events
@@ -3282,22 +3288,22 @@
}
@Test
- public void testZenModeEventLog_policyChanges(@TestParameter ModesApiFlag modesApiFlag)
+ public void testZenModeEventLog_policyChanges(@TestParameter ModesFlag modesFlag)
throws IllegalArgumentException {
- modesApiFlag.applyFlag(mSetFlagsRule);
+ modesFlag.applyFlags(mSetFlagsRule);
mTestFlagResolver.setFlagOverride(LOG_DND_STATE_EVENTS, true);
setupZenConfig();
// First just turn zen mode on
mZenModeHelper.setManualZenMode(ZEN_MODE_IMPORTANT_INTERRUPTIONS, null,
- modesApiFlag.mOriginForUserActionInSystemUi, "", null, Process.SYSTEM_UID);
+ modesFlag.mOriginForUserActionInSystemUi, "", null, Process.SYSTEM_UID);
// Now change the policy slightly; want to confirm that this'll be reflected in the logs
ZenModeConfig newConfig = mZenModeHelper.mConfig.copy();
newConfig.allowAlarms = true;
newConfig.allowRepeatCallers = false;
mZenModeHelper.setNotificationPolicy(newConfig.toNotificationPolicy(),
- modesApiFlag.mOriginForUserActionInSystemUi, Process.SYSTEM_UID);
+ modesFlag.mOriginForUserActionInSystemUi, Process.SYSTEM_UID);
// Turn zen mode off; we want to make sure policy changes do not get logged when zen mode
// is off.
@@ -3308,7 +3314,7 @@
newConfig.allowMessages = false;
newConfig.allowRepeatCallers = true;
mZenModeHelper.setNotificationPolicy(newConfig.toNotificationPolicy(),
- modesApiFlag.mOriginForUserActionInSystemUi, Process.SYSTEM_UID);
+ modesFlag.mOriginForUserActionInSystemUi, Process.SYSTEM_UID);
// Total events: we only expect ones for turning on, changing policy, and turning off
assertEquals(3, mZenModeEventLogger.numLoggedChanges());
@@ -3341,9 +3347,9 @@
}
@Test
- public void testZenModeEventLog_ruleCounts(@TestParameter ModesApiFlag modesApiFlag)
+ public void testZenModeEventLog_ruleCounts(@TestParameter ModesFlag modesFlag)
throws IllegalArgumentException {
- modesApiFlag.applyFlag(mSetFlagsRule);
+ modesFlag.applyFlags(mSetFlagsRule);
mTestFlagResolver.setFlagOverride(LOG_DND_STATE_EVENTS, true);
setupZenConfig();
@@ -3447,9 +3453,9 @@
@Test
public void testZenModeEventLog_noLogWithNoConfigChange(
- @TestParameter ModesApiFlag modesApiFlag) throws IllegalArgumentException {
+ @TestParameter ModesFlag modesFlag) throws IllegalArgumentException {
// If evaluateZenMode is called independently of a config change, don't log.
- modesApiFlag.applyFlag(mSetFlagsRule);
+ modesFlag.applyFlags(mSetFlagsRule);
mTestFlagResolver.setFlagOverride(LOG_DND_STATE_EVENTS, true);
setupZenConfig();
@@ -3466,11 +3472,11 @@
}
@Test
- public void testZenModeEventLog_reassignUid(@TestParameter ModesApiFlag modesApiFlag)
+ public void testZenModeEventLog_reassignUid(@TestParameter ModesFlag modesFlag)
throws IllegalArgumentException {
// Test that, only in specific cases, we reassign the calling UID to one associated with
// the automatic rule owner.
- modesApiFlag.applyFlag(mSetFlagsRule);
+ modesFlag.applyFlags(mSetFlagsRule);
mTestFlagResolver.setFlagOverride(LOG_DND_STATE_EVENTS, true);
setupZenConfig();
@@ -3496,7 +3502,7 @@
manualRulePolicy,
NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
String id2 = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), zenRule2,
- modesApiFlag.mOriginForUserActionInSystemUi, "test", Process.SYSTEM_UID);
+ modesFlag.mOriginForUserActionInSystemUi, "test", Process.SYSTEM_UID);
// Turn on rule 1; call looks like it's from the system. Because setting a condition is
// typically an automatic (non-user-initiated) action, expect the calling UID to be
@@ -3515,7 +3521,7 @@
// from the system-provided one.
zenRule.setEnabled(false);
mZenModeHelper.updateAutomaticZenRule(id, zenRule,
- modesApiFlag.mOriginForUserActionInSystemUi, "", Process.SYSTEM_UID);
+ modesFlag.mOriginForUserActionInSystemUi, "", Process.SYSTEM_UID);
// Add a manual rule. Any manual rule changes should not get calling uids reassigned.
mZenModeHelper.setManualZenMode(ZEN_MODE_IMPORTANT_INTERRUPTIONS, null, UPDATE_ORIGIN_APP,
@@ -3573,9 +3579,9 @@
@Test
public void testZenModeEventLog_channelsBypassingChanges(
- @TestParameter ModesApiFlag modesApiFlag) {
+ @TestParameter ModesFlag modesFlag) {
// Verify that the right thing happens when the canBypassDnd value changes.
- modesApiFlag.applyFlag(mSetFlagsRule);
+ modesFlag.applyFlags(mSetFlagsRule);
mTestFlagResolver.setFlagOverride(LOG_DND_STATE_EVENTS, true);
setupZenConfig();
@@ -3847,8 +3853,9 @@
}
@Test
- @EnableFlags(Flags.FLAG_MODES_API)
- public void testUpdateConsolidatedPolicy_modesApiDefaultRulesOnly_takesDeviceDefault() {
+ public void testUpdateConsolidatedPolicy_modesApiDefaultRulesOnly_takesDefault(
+ @TestParameter({"MODES_UI", "MODES_API"}) ModesFlag modesFlag) {
+ modesFlag.applyFlags(mSetFlagsRule);
setupZenConfig();
// When there's one automatic rule active and it doesn't specify a policy, test that the
@@ -3869,7 +3876,9 @@
// inspect the consolidated policy, which should match the device default settings.
assertThat(ZenAdapters.notificationPolicyToZenPolicy(mZenModeHelper.mConsolidatedPolicy))
- .isEqualTo(mZenModeHelper.getDefaultZenPolicy());
+ .isEqualTo(modesFlag == ModesFlag.MODES_UI
+ ? mZenModeHelper.getDefaultZenPolicy()
+ : mZenModeHelper.mConfig.toZenPolicy());
}
@Test
@@ -3904,7 +3913,8 @@
UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID);
// since this is the only active rule, the consolidated policy should match the custom
- // policy for every field specified, and take default values for unspecified things
+ // policy for every field specified, and take default values (from device default or
+ // manual policy) for unspecified things
assertTrue(mZenModeHelper.mConsolidatedPolicy.allowAlarms()); // custom
assertTrue(mZenModeHelper.mConsolidatedPolicy.allowMedia()); // custom
assertFalse(mZenModeHelper.mConsolidatedPolicy.allowSystem()); // default
@@ -3918,8 +3928,9 @@
}
@Test
- @EnableFlags(Flags.FLAG_MODES_API)
- public void testUpdateConsolidatedPolicy_modesApiCustomPolicyOnly_fillInWithDeviceDefault() {
+ public void testUpdateConsolidatedPolicy_modesApiCustomPolicyOnly_fillInWithDefault(
+ @TestParameter({"MODES_UI", "MODES_API"}) ModesFlag modesFlag) {
+ modesFlag.applyFlags(mSetFlagsRule);
setupZenConfig();
// when there's only one automatic rule active and it has a custom policy, make sure that's
@@ -3948,11 +3959,15 @@
UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID);
// since this is the only active rule, the consolidated policy should match the custom
- // policy for every field specified, and take default values for unspecified things
- assertThat(mZenModeHelper.mConsolidatedPolicy.allowAlarms()).isTrue(); // default
- assertThat(mZenModeHelper.mConsolidatedPolicy.allowMedia()).isTrue(); // default
+ // policy for every field specified, and take default values (from either device default
+ // policy or manual rule) for unspecified things
+ assertThat(mZenModeHelper.mConsolidatedPolicy.allowAlarms()).isEqualTo(
+ modesFlag == ModesFlag.MODES_UI ? true : false); // default
+ assertThat(mZenModeHelper.mConsolidatedPolicy.allowMedia()).isEqualTo(
+ modesFlag == ModesFlag.MODES_UI ? true : false); // default
assertThat(mZenModeHelper.mConsolidatedPolicy.allowSystem()).isTrue(); // custom
- assertThat(mZenModeHelper.mConsolidatedPolicy.allowReminders()).isFalse(); // default
+ assertThat(mZenModeHelper.mConsolidatedPolicy.allowReminders()).isEqualTo(
+ modesFlag == ModesFlag.MODES_UI ? false : true); // default
assertThat(mZenModeHelper.mConsolidatedPolicy.allowCalls()).isFalse(); // custom
assertThat(mZenModeHelper.mConsolidatedPolicy.allowMessages()).isTrue(); // default
assertThat(mZenModeHelper.mConsolidatedPolicy.allowRepeatCallers()).isFalse(); // custom
@@ -4022,8 +4037,9 @@
}
@Test
- @EnableFlags(Flags.FLAG_MODES_API)
- public void testUpdateConsolidatedPolicy_modesApiDefaultAndCustomActive_mergesWithDefault() {
+ public void testUpdateConsolidatedPolicy_modesApiDefaultAndCustomActive_mergesWithDefault(
+ @TestParameter({"MODES_UI", "MODES_API"}) ModesFlag modesFlag) {
+ modesFlag.applyFlags(mSetFlagsRule);
setupZenConfig();
// when there are two rules active, one inheriting the default policy and one setting its
@@ -4071,16 +4087,19 @@
// now both rules should be on, and the consolidated policy should reflect the most
// restrictive option of each of the two
assertThat(mZenModeHelper.mConsolidatedPolicy.allowAlarms()).isFalse(); // custom stricter
- assertThat(mZenModeHelper.mConsolidatedPolicy.allowMedia()).isTrue(); // default
+ assertThat(mZenModeHelper.mConsolidatedPolicy.allowMedia()).isEqualTo(
+ modesFlag == ModesFlag.MODES_UI ? true : false); // default
assertThat(mZenModeHelper.mConsolidatedPolicy.allowSystem()).isFalse(); // default stricter
- assertThat(mZenModeHelper.mConsolidatedPolicy.allowReminders()).isFalse(); // default
+ assertThat(mZenModeHelper.mConsolidatedPolicy.allowReminders()).isEqualTo(
+ modesFlag == ModesFlag.MODES_UI ? false : true); // default
assertThat(mZenModeHelper.mConsolidatedPolicy.allowCalls()).isFalse(); // custom stricter
assertThat(mZenModeHelper.mConsolidatedPolicy.allowMessages()).isTrue(); // default
assertThat(mZenModeHelper.mConsolidatedPolicy.allowConversations()).isTrue(); // default
assertThat(mZenModeHelper.mConsolidatedPolicy.allowRepeatCallers())
.isFalse(); // custom stricter
assertThat(mZenModeHelper.mConsolidatedPolicy.showBadges()).isFalse(); // custom stricter
- assertThat(mZenModeHelper.mConsolidatedPolicy.showPeeking()).isFalse(); // default stricter
+ assertThat(mZenModeHelper.mConsolidatedPolicy.showPeeking()).isEqualTo(
+ modesFlag == ModesFlag.MODES_UI ? false : true); // default
}
@Test
@@ -4134,8 +4153,9 @@
}
@Test
- @EnableFlags(Flags.FLAG_MODES_API)
- public void testUpdateConsolidatedPolicy_ignoresActiveRulesWithInterruptionFilterAll() {
+ public void testUpdateConsolidatedPolicy_ignoresActiveRulesWithInterruptionFilterAll(
+ @TestParameter({"MODES_UI", "MODES_API"}) ModesFlag modesFlag) {
+ modesFlag.applyFlags(mSetFlagsRule);
setupZenConfig();
// Rules with INTERRUPTION_FILTER_ALL are skipped when calculating consolidated policy.
@@ -4172,10 +4192,12 @@
UPDATE_ORIGIN_APP, CUSTOM_PKG_UID);
// Consolidated Policy should be default + rule1.
- assertThat(mZenModeHelper.mConsolidatedPolicy.allowAlarms()).isTrue(); // default
+ assertThat(mZenModeHelper.mConsolidatedPolicy.allowAlarms()).isEqualTo(
+ modesFlag == ModesFlag.MODES_UI ? true : false); // default
assertThat(mZenModeHelper.mConsolidatedPolicy.allowMedia()).isTrue(); // priority rule
assertThat(mZenModeHelper.mConsolidatedPolicy.allowSystem()).isTrue(); // priority rule
- assertThat(mZenModeHelper.mConsolidatedPolicy.allowReminders()).isFalse(); // default
+ assertThat(mZenModeHelper.mConsolidatedPolicy.allowReminders()).isEqualTo(
+ modesFlag == ModesFlag.MODES_UI ? false : true); // default
assertThat(mZenModeHelper.mConsolidatedPolicy.allowCalls()).isTrue(); // default
assertThat(mZenModeHelper.mConsolidatedPolicy.allowMessages()).isTrue(); // default
assertThat(mZenModeHelper.mConsolidatedPolicy.allowConversations()).isTrue(); // default
@@ -6251,7 +6273,7 @@
}
private void checkDndProtoMatchesDefaultZenConfig(DNDPolicyProto dndProto) {
- if (!Flags.modesApi()) {
+ if (!Flags.modesUi()) {
checkDndProtoMatchesSetupZenConfig(dndProto);
return;
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 1da5001..b0a3374 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -525,10 +525,13 @@
// The activity shouldn't start relaunching since it doesn't have any desk resources.
assertFalse(activity.isRelaunching());
+ // The activity configuration ui mode should match.
+ final var activityConfig = activity.getConfiguration();
+ assertEquals(newConfig.uiMode, activityConfig.uiMode);
// The configuration change is still sent to the activity, even if it doesn't relaunch.
final ActivityConfigurationChangeItem expected =
- ActivityConfigurationChangeItem.obtain(activity.token, newConfig,
+ ActivityConfigurationChangeItem.obtain(activity.token, activityConfig,
activity.getActivityWindowInfo());
verify(mClientLifecycleManager).scheduleTransactionItem(
eq(activity.app.getThread()), eq(expected));
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index 10eae57..1355092 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -46,7 +46,6 @@
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.Process.SYSTEM_UID;
-import static android.server.wm.ActivityManagerTestBase.isTablet;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.clearInvocations;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
@@ -76,7 +75,6 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
-import static org.junit.Assume.assumeFalse;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -124,7 +122,6 @@
import com.android.server.wm.BackgroundActivityStartController.BalVerdict;
import com.android.server.wm.LaunchParamsController.LaunchParamsModifier;
import com.android.server.wm.utils.MockTracker;
-import com.android.window.flags.Flags;
import org.junit.After;
import org.junit.Before;
@@ -1298,12 +1295,6 @@
*/
@Test
public void testDeliverIntentToTopActivityOfNonTopDisplay() {
- // TODO(b/330152508): Remove check once legacy multi-display behaviour can coexist with
- // desktop windowing mode
- // Ignore test if desktop windowing is enabled on tablets as legacy multi-display
- // behaviour will not be respected
- assumeFalse(Flags.enableDesktopWindowingMode() && isTablet());
-
final ActivityStarter starter = prepareStarter(FLAG_ACTIVITY_NEW_TASK,
false /* mockGetRootTask */);
diff --git a/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java
index f92387c..a268aa9 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java
@@ -79,19 +79,19 @@
@Test
@DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
- public void testReturnsContinueIfDesktopWindowingIsDisabled() {
+ public void testReturnsSkipIfDesktopWindowingIsDisabled() {
setupDesktopModeLaunchParamsModifier();
- assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(null).calculate());
+ assertEquals(RESULT_SKIP, new CalculateRequestBuilder().setTask(null).calculate());
}
@Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
- public void testReturnsContinueIfDesktopWindowingIsEnabledOnUnsupportedDevice() {
+ public void testReturnsSkipIfDesktopWindowingIsEnabledOnUnsupportedDevice() {
setupDesktopModeLaunchParamsModifier(/*isDesktopModeSupported=*/ false,
/*enforceDeviceRestrictions=*/ true);
- assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(null).calculate());
+ assertEquals(RESULT_SKIP, new CalculateRequestBuilder().setTask(null).calculate());
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 27d9d13..44d1b54 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -114,6 +114,8 @@
import android.os.Binder;
import android.os.RemoteException;
import android.os.SystemClock;
+import android.os.UserHandle;
+import android.os.UserManager;
import android.platform.test.annotations.Presubmit;
import android.platform.test.annotations.RequiresFlagsDisabled;
import android.platform.test.flag.junit.CheckFlagsRule;
@@ -2813,6 +2815,41 @@
mDisplayContent.getKeepClearAreas());
}
+ @Test
+ public void testHasAccessConsidersUserVisibilityForBackgroundVisibleUsers() {
+ doReturn(true).when(() -> UserManager.isVisibleBackgroundUsersEnabled());
+ final int appId = 1234;
+ final int userId1 = 11;
+ final int userId2 = 12;
+ final int uid1 = UserHandle.getUid(userId1, appId);
+ final int uid2 = UserHandle.getUid(userId2, appId);
+ final DisplayInfo displayInfo = new DisplayInfo(mDisplayInfo);
+ final DisplayContent dc = createNewDisplay(displayInfo);
+ int displayId = dc.getDisplayId();
+ doReturn(true).when(mWm.mUmInternal).isUserVisible(userId1, displayId);
+ doReturn(false).when(mWm.mUmInternal).isUserVisible(userId2, displayId);
+
+ assertTrue(dc.hasAccess(uid1));
+ assertFalse(dc.hasAccess(uid2));
+ }
+
+ @Test
+ public void testHasAccessIgnoresUserVisibilityForPrivateDisplay() {
+ doReturn(true).when(() -> UserManager.isVisibleBackgroundUsersEnabled());
+ final int appId = 1234;
+ final int userId2 = 12;
+ final int uid2 = UserHandle.getUid(userId2, appId);
+ final DisplayInfo displayInfo = new DisplayInfo(mDisplayInfo);
+ displayInfo.flags = FLAG_PRIVATE;
+ displayInfo.ownerUid = uid2;
+ final DisplayContent dc = createNewDisplay(displayInfo);
+ int displayId = dc.getDisplayId();
+
+ assertTrue(dc.hasAccess(uid2));
+
+ verify(mWm.mUmInternal, never()).isUserVisible(userId2, displayId);
+ }
+
private void removeRootTaskTests(Runnable runnable) {
final TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
final Task rootTask1 = taskDisplayArea.createRootTask(WINDOWING_MODE_FULLSCREEN,
diff --git a/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java
index b74da1a..a60d243 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java
@@ -85,6 +85,8 @@
import android.content.pm.PackageManager.Property;
import android.content.res.Resources;
import android.graphics.Rect;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
import android.platform.test.annotations.Presubmit;
import android.view.InsetsSource;
import android.view.InsetsState;
@@ -96,6 +98,7 @@
import androidx.test.filters.SmallTest;
import com.android.internal.R;
+import com.android.window.flags.Flags;
import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
@@ -1528,6 +1531,98 @@
mActivity.getParent().getConfiguration()), /* delta */ 0.01);
}
+ @Test
+ public void testIsVerticalThinLetterboxed() {
+ // Vertical thin letterbox disabled
+ doReturn(-1).when(mActivity.mWmService.mLetterboxConfiguration)
+ .getThinLetterboxHeightPx();
+ assertFalse(mController.isVerticalThinLetterboxed());
+ // Define a Task 100x100
+ final Task task = mock(Task.class);
+ doReturn(new Rect(0, 0, 100, 100)).when(task).getBounds();
+ doReturn(10).when(mActivity.mWmService.mLetterboxConfiguration)
+ .getThinLetterboxHeightPx();
+
+ // Vertical thin letterbox disabled without Task
+ doReturn(null).when(mActivity).getTask();
+ assertFalse(mController.isVerticalThinLetterboxed());
+ // Assign a Task for the Activity
+ doReturn(task).when(mActivity).getTask();
+
+ // (task.width() - act.width()) / 2 = 5 < 10
+ doReturn(new Rect(5, 5, 95, 95)).when(mActivity).getBounds();
+ assertTrue(mController.isVerticalThinLetterboxed());
+
+ // (task.width() - act.width()) / 2 = 10 = 10
+ doReturn(new Rect(10, 10, 90, 90)).when(mActivity).getBounds();
+ assertTrue(mController.isVerticalThinLetterboxed());
+
+ // (task.width() - act.width()) / 2 = 11 > 10
+ doReturn(new Rect(11, 11, 89, 89)).when(mActivity).getBounds();
+ assertFalse(mController.isVerticalThinLetterboxed());
+ }
+
+ @Test
+ public void testIsHorizontalThinLetterboxed() {
+ // Horizontal thin letterbox disabled
+ doReturn(-1).when(mActivity.mWmService.mLetterboxConfiguration)
+ .getThinLetterboxWidthPx();
+ assertFalse(mController.isHorizontalThinLetterboxed());
+ // Define a Task 100x100
+ final Task task = mock(Task.class);
+ doReturn(new Rect(0, 0, 100, 100)).when(task).getBounds();
+ doReturn(10).when(mActivity.mWmService.mLetterboxConfiguration)
+ .getThinLetterboxWidthPx();
+
+ // Vertical thin letterbox disabled without Task
+ doReturn(null).when(mActivity).getTask();
+ assertFalse(mController.isHorizontalThinLetterboxed());
+ // Assign a Task for the Activity
+ doReturn(task).when(mActivity).getTask();
+
+ // (task.height() - act.height()) / 2 = 5 < 10
+ doReturn(new Rect(5, 5, 95, 95)).when(mActivity).getBounds();
+ assertTrue(mController.isHorizontalThinLetterboxed());
+
+ // (task.height() - act.height()) / 2 = 10 = 10
+ doReturn(new Rect(10, 10, 90, 90)).when(mActivity).getBounds();
+ assertTrue(mController.isHorizontalThinLetterboxed());
+
+ // (task.height() - act.height()) / 2 = 11 > 10
+ doReturn(new Rect(11, 11, 89, 89)).when(mActivity).getBounds();
+ assertFalse(mController.isHorizontalThinLetterboxed());
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_DISABLE_THIN_LETTERBOXING_REACHABILITY)
+ public void testAllowReachabilityForThinLetterboxWithFlagEnabled() {
+ spyOn(mController);
+ doReturn(true).when(mController).isVerticalThinLetterboxed();
+ assertFalse(mController.allowVerticalReachabilityForThinLetterbox());
+ doReturn(true).when(mController).isHorizontalThinLetterboxed();
+ assertFalse(mController.allowHorizontalReachabilityForThinLetterbox());
+
+ doReturn(false).when(mController).isVerticalThinLetterboxed();
+ assertTrue(mController.allowVerticalReachabilityForThinLetterbox());
+ doReturn(false).when(mController).isHorizontalThinLetterboxed();
+ assertTrue(mController.allowHorizontalReachabilityForThinLetterbox());
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_DISABLE_THIN_LETTERBOXING_REACHABILITY)
+ public void testAllowReachabilityForThinLetterboxWithFlagDisabled() {
+ spyOn(mController);
+ doReturn(true).when(mController).isVerticalThinLetterboxed();
+ assertTrue(mController.allowVerticalReachabilityForThinLetterbox());
+ doReturn(true).when(mController).isHorizontalThinLetterboxed();
+ assertTrue(mController.allowHorizontalReachabilityForThinLetterbox());
+
+ doReturn(false).when(mController).isVerticalThinLetterboxed();
+ assertTrue(mController.allowVerticalReachabilityForThinLetterbox());
+ doReturn(false).when(mController).isHorizontalThinLetterboxed();
+ assertTrue(mController.allowHorizontalReachabilityForThinLetterbox());
+ }
+
private void mockThatProperty(String propertyName, boolean value) throws Exception {
Property property = new Property(propertyName, /* value */ value, /* packageName */ "",
/* className */ "");
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
index 75b84d1..6ec1429 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
@@ -1373,26 +1373,6 @@
assertTrue(info.supportsMultiWindow);
}
- @Test
- public void testRemoveCompatibleRecentTask() {
- final Task task1 = createTaskBuilder(".Task").setWindowingMode(
- WINDOWING_MODE_FULLSCREEN).build();
- mRecentTasks.add(task1);
- final Task task2 = createTaskBuilder(".Task").setWindowingMode(
- WINDOWING_MODE_MULTI_WINDOW).build();
- mRecentTasks.add(task2);
- assertEquals(2, mRecentTasks.getRecentTasks(MAX_VALUE, 0 /* flags */,
- true /* getTasksAllowed */, TEST_USER_0_ID, 0).getList().size());
-
- // Set windowing mode and ensure the same fullscreen task that created earlier is removed.
- task2.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
- mRecentTasks.removeCompatibleRecentTask(task2);
- assertEquals(1, mRecentTasks.getRecentTasks(MAX_VALUE, 0 /* flags */,
- true /* getTasksAllowed */, TEST_USER_0_ID, 0).getList().size());
- assertEquals(task2.mTaskId, mRecentTasks.getRecentTasks(MAX_VALUE, 0 /* flags */,
- true /* getTasksAllowed */, TEST_USER_0_ID, 0).getList().get(0).taskId);
- }
-
private TaskSnapshot createSnapshot(Point taskSize, Point bufferSize) {
HardwareBuffer buffer = null;
if (bufferSize != null) {
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index 8677738..6b605ec 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -3646,11 +3646,27 @@
}
@Test
+ public void testIsReachabilityEnabled_thisLetterbox_false() {
+ // Case when the reachability would be enabled otherwise
+ setUpDisplaySizeWithApp(/* dw */ 1000, /* dh */ 2800);
+ mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+ mWm.mLetterboxConfiguration.setIsVerticalReachabilityEnabled(true);
+ prepareUnresizable(mActivity, SCREEN_ORIENTATION_LANDSCAPE);
+ mActivity.getWindowConfiguration().setBounds(null);
+
+ setUpAllowThinLetterboxed(/* thinLetterboxAllowed */ false);
+
+ assertFalse(mActivity.mLetterboxUiController.isVerticalReachabilityEnabled());
+ assertFalse(mActivity.mLetterboxUiController.isHorizontalReachabilityEnabled());
+ }
+
+ @Test
public void testIsHorizontalReachabilityEnabled_splitScreen_false() {
mAtm.mDevEnableNonResizableMultiWindow = true;
setUpDisplaySizeWithApp(2800, 1000);
mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
mWm.mLetterboxConfiguration.setIsHorizontalReachabilityEnabled(true);
+ setUpAllowThinLetterboxed(/* thinLetterboxAllowed */ true);
final TestSplitOrganizer organizer =
new TestSplitOrganizer(mAtm, mActivity.getDisplayContent());
@@ -3673,6 +3689,7 @@
setUpDisplaySizeWithApp(1000, 2800);
mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
mWm.mLetterboxConfiguration.setIsVerticalReachabilityEnabled(true);
+ setUpAllowThinLetterboxed(/* thinLetterboxAllowed */ true);
final TestSplitOrganizer organizer =
new TestSplitOrganizer(mAtm, mActivity.getDisplayContent());
@@ -3694,6 +3711,7 @@
setUpDisplaySizeWithApp(1000, 2800);
mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
mWm.mLetterboxConfiguration.setIsVerticalReachabilityEnabled(true);
+ setUpAllowThinLetterboxed(/* thinLetterboxAllowed */ true);
// Unresizable landscape-only activity.
prepareUnresizable(mActivity, 1.1f, SCREEN_ORIENTATION_LANDSCAPE);
@@ -3715,6 +3733,7 @@
setUpDisplaySizeWithApp(/* dw */ 1000, /* dh */ 2800);
mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
mWm.mLetterboxConfiguration.setIsVerticalReachabilityEnabled(true);
+ setUpAllowThinLetterboxed(/* thinLetterboxAllowed */ true);
prepareUnresizable(mActivity, SCREEN_ORIENTATION_LANDSCAPE);
@@ -3731,6 +3750,7 @@
setUpDisplaySizeWithApp(/* dw */ 2800, /* dh */ 1000);
mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
mWm.mLetterboxConfiguration.setIsHorizontalReachabilityEnabled(true);
+ setUpAllowThinLetterboxed(/* thinLetterboxAllowed */ true);
prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT);
@@ -3747,6 +3767,7 @@
// Portrait display
setUpDisplaySizeWithApp(1400, 1600);
mActivity.mWmService.mLetterboxConfiguration.setIsHorizontalReachabilityEnabled(true);
+ setUpAllowThinLetterboxed(/* thinLetterboxAllowed */ true);
// 16:9f unresizable portrait app
prepareMinAspectRatio(mActivity, OVERRIDE_MIN_ASPECT_RATIO_LARGE_VALUE,
@@ -3760,6 +3781,7 @@
// Landscape display
setUpDisplaySizeWithApp(1600, 1500);
mActivity.mWmService.mLetterboxConfiguration.setIsVerticalReachabilityEnabled(true);
+ setUpAllowThinLetterboxed(/* thinLetterboxAllowed */ true);
// 16:9f unresizable landscape app
prepareMinAspectRatio(mActivity, OVERRIDE_MIN_ASPECT_RATIO_LARGE_VALUE,
@@ -3773,6 +3795,7 @@
setUpDisplaySizeWithApp(2800, 1000);
mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
mWm.mLetterboxConfiguration.setIsHorizontalReachabilityEnabled(true);
+ setUpAllowThinLetterboxed(/* thinLetterboxAllowed */ true);
// Unresizable portrait-only activity.
prepareUnresizable(mActivity, 1.1f, SCREEN_ORIENTATION_PORTRAIT);
@@ -3794,6 +3817,7 @@
setUpDisplaySizeWithApp(1800, 2200);
mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
mWm.mLetterboxConfiguration.setIsHorizontalReachabilityEnabled(true);
+ setUpAllowThinLetterboxed(/* thinLetterboxAllowed */ true);
// Unresizable portrait-only activity.
prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT);
@@ -3815,6 +3839,7 @@
setUpDisplaySizeWithApp(2200, 1800);
mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
mWm.mLetterboxConfiguration.setIsVerticalReachabilityEnabled(true);
+ setUpAllowThinLetterboxed(/* thinLetterboxAllowed */ true);
// Unresizable landscape-only activity.
prepareUnresizable(mActivity, SCREEN_ORIENTATION_LANDSCAPE);
@@ -5011,6 +5036,14 @@
assertFalse(activity.shouldSendCompatFakeFocus());
}
+ private void setUpAllowThinLetterboxed(boolean thinLetterboxAllowed) {
+ spyOn(mActivity.mLetterboxUiController);
+ doReturn(thinLetterboxAllowed).when(mActivity.mLetterboxUiController)
+ .allowVerticalReachabilityForThinLetterbox();
+ doReturn(thinLetterboxAllowed).when(mActivity.mLetterboxUiController)
+ .allowHorizontalReachabilityForThinLetterbox();
+ }
+
private int getExpectedSplitSize(int dimensionToSplit) {
int dividerWindowWidth =
mActivity.mWmService.mContext.getResources().getDimensionPixelSize(
diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
index 87f26e5..c45c86c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -56,6 +56,7 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManagerInternal;
+import android.content.res.Configuration;
import android.database.ContentObserver;
import android.hardware.devicestate.DeviceStateManager;
import android.hardware.display.DisplayManagerGlobal;
@@ -86,6 +87,7 @@
import com.android.server.display.DisplayControl;
import com.android.server.display.color.ColorDisplayService;
import com.android.server.firewall.IntentFirewall;
+import com.android.server.grammaticalinflection.GrammaticalInflectionManagerInternal;
import com.android.server.input.InputManagerService;
import com.android.server.pm.UserManagerInternal;
import com.android.server.pm.UserManagerService;
@@ -208,6 +210,11 @@
setUpLocalServices();
setUpActivityTaskManagerService();
setUpWindowManagerService();
+
+ // We never load the system settings in the tests, thus need to setup the grammatical
+ // gender configuration explicitly.
+ mAtmService.getGlobalConfiguration().setGrammaticalGender(
+ Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED);
}
private void setUpSystemCore() {
@@ -337,6 +344,18 @@
};
when(umi.isUserVisible(anyInt())).thenAnswer(isUserVisibleAnswer);
when(umi.isUserVisible(anyInt(), anyInt())).thenAnswer(isUserVisibleAnswer);
+
+ final var gimi = mock(
+ GrammaticalInflectionManagerInternal.class, withSettings().stubOnly());
+ doReturn(Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED).when(
+ gimi).getGrammaticalGenderFromDeveloperSettings();
+ doReturn(Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED).when(
+ gimi).getSystemGrammaticalGender(anyInt());
+ doReturn(Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED).when(
+ gimi).mergedFinalSystemGrammaticalGender();
+ doReturn(false).when(gimi).canGetSystemGrammaticalGender(anyInt());
+ doReturn(gimi).when(
+ () -> LocalServices.getService(GrammaticalInflectionManagerInternal.class));
}
private void setUpActivityTaskManagerService() {
@@ -475,6 +494,7 @@
LocalServices.removeServiceForTest(StatusBarManagerInternal.class);
LocalServices.removeServiceForTest(UserManagerInternal.class);
LocalServices.removeServiceForTest(ImeTargetVisibilityPolicy.class);
+ LocalServices.removeServiceForTest(GrammaticalInflectionManagerInternal.class);
}
Description getDescription() {
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
index 83e4151..afa6698 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
@@ -487,6 +487,16 @@
// Flush EVENT_APPEARED.
mController.dispatchPendingEvents();
+ // Even if the activity is not launched in an organized TaskFragment, it is still considered
+ // as the remote activity to the organizer process. Because when the task becomes visible,
+ // the organizer process needs to be interactive (unfrozen) to receive TaskFragment events.
+ activity.setVisibleRequested(true);
+ activity.setState(ActivityRecord.State.RESUMED, "test");
+ assertTrue(organizerProc.hasVisibleActivities());
+ activity.setVisibleRequested(false);
+ activity.setState(ActivityRecord.State.STOPPED, "test");
+ assertFalse(organizerProc.hasVisibleActivities());
+
// Make sure the activity belongs to the same app, but it is in a different pid.
activity.info.applicationInfo.uid = uid;
doReturn(pid + 1).when(activity).getPid();
diff --git a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
index 3288788..80c066d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
@@ -1236,7 +1236,9 @@
final WindowState statusBar = createWindow(null, TYPE_STATUS_BAR, "statusBar");
makeWindowVisible(statusBar);
mDisplayContent.getDisplayPolicy().addWindowLw(statusBar, statusBar.mAttrs);
- final WindowState navBar = createWindow(null, TYPE_NAVIGATION_BAR, "navBar");
+ final WindowState navBar = createNavBarWithProvidedInsets(mDisplayContent);
+ final InsetsSourceProvider navBarInsetsProvider = navBar.getControllableInsetProvider();
+ assertNotNull(navBarInsetsProvider);
final ActivityRecord app = createActivityRecord(mDisplayContent);
final Transition transition = app.mTransitionController.createTransition(TRANSIT_OPEN);
app.mTransitionController.requestStartTransition(transition, app.getTask(),
@@ -1282,11 +1284,15 @@
onRotationTransactionReady(player, mWm.mTransactionFactory.get()).onTransactionCommitted();
assertEquals(ROTATION_ANIMATION_SEAMLESS, player.mLastReady.getChange(
mDisplayContent.mRemoteToken.toWindowContainerToken()).getRotationAnimation());
+ spyOn(navBarInsetsProvider);
player.finish();
// The controller should be cleared if the target windows are drawn.
statusBar.finishDrawing(mWm.mTransactionFactory.get(), Integer.MAX_VALUE);
assertNull(mDisplayContent.getAsyncRotationController());
+ // The shouldFreezeInsetsPosition for navBar was true, so its insets position should be
+ // updated if the transition is done.
+ verify(navBarInsetsProvider).updateInsetsControlPosition(navBar);
}
private static void assertShouldFreezeInsetsPosition(AsyncRotationController controller,
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
index a78fc10..7e6301f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
@@ -21,13 +21,15 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.permission.flags.Flags.FLAG_SENSITIVE_CONTENT_IMPROVEMENTS;
+import static android.permission.flags.Flags.FLAG_SENSITIVE_CONTENT_RECENTS_SCREENSHOT_BUGFIX;
import static android.permission.flags.Flags.FLAG_SENSITIVE_NOTIFICATION_APP_PROTECTION;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.FLAG_OWN_FOCUS;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
-import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_SENSITIVE_FOR_TRACING;
+import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_SENSITIVE_FOR_PRIVACY;
import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_SPY;
import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
@@ -1020,6 +1022,35 @@
}
@Test
+ @RequiresFlagsEnabled(
+ {FLAG_SENSITIVE_NOTIFICATION_APP_PROTECTION, FLAG_SENSITIVE_CONTENT_IMPROVEMENTS,
+ FLAG_SENSITIVE_CONTENT_RECENTS_SCREENSHOT_BUGFIX})
+ public void addBlockScreenCaptureForApps_appNotInForeground_invalidateSnapshot() {
+ spyOn(mWm.mTaskSnapshotController);
+
+ // createAppWindow uses package name of "test" and uid of "0"
+ String testPackage = "test";
+ int ownerId1 = 0;
+
+ final Task task = createTask(mDisplayContent);
+ final WindowState win = createAppWindow(task, ACTIVITY_TYPE_STANDARD, "appWindow");
+ mWm.mWindowMap.put(win.mClient.asBinder(), win);
+ final ActivityRecord activity = win.mActivityRecord;
+ activity.setVisibleRequested(false);
+ activity.setVisible(false);
+ win.setHasSurface(false);
+
+ PackageInfo blockedPackage = new PackageInfo(testPackage, ownerId1);
+ ArraySet<PackageInfo> blockedPackages = new ArraySet();
+ blockedPackages.add(blockedPackage);
+
+ WindowManagerInternal wmInternal = LocalServices.getService(WindowManagerInternal.class);
+ wmInternal.addBlockScreenCaptureForApps(blockedPackages);
+
+ verify(mWm.mTaskSnapshotController).removeAndDeleteSnapshot(anyInt(), eq(ownerId1));
+ }
+
+ @Test
public void clearBlockedApps_clearsCache() {
String testPackage = "test";
int ownerId1 = 20;
@@ -1192,20 +1223,20 @@
final InputChannel inputChannel = new InputChannel();
mWm.grantInputChannel(session, callingUid, callingPid, DEFAULT_DISPLAY, surfaceControl,
window, null /* hostInputToken */, FLAG_NOT_FOCUSABLE, 0 /* privateFlags */,
- INPUT_FEATURE_SENSITIVE_FOR_TRACING, TYPE_APPLICATION, null /* windowToken */,
+ INPUT_FEATURE_SENSITIVE_FOR_PRIVACY, TYPE_APPLICATION, null /* windowToken */,
inputTransferToken,
"TestInputChannel", inputChannel);
verify(mTransaction).setInputWindowInfo(
eq(surfaceControl),
- argThat(h -> (h.inputConfig & InputConfig.SENSITIVE_FOR_TRACING) == 0));
+ argThat(h -> (h.inputConfig & InputConfig.SENSITIVE_FOR_PRIVACY) == 0));
mWm.updateInputChannel(inputChannel.getToken(), DEFAULT_DISPLAY, surfaceControl,
FLAG_NOT_FOCUSABLE, PRIVATE_FLAG_TRUSTED_OVERLAY,
- INPUT_FEATURE_SENSITIVE_FOR_TRACING,
+ INPUT_FEATURE_SENSITIVE_FOR_PRIVACY,
null /* region */);
verify(mTransaction).setInputWindowInfo(
eq(surfaceControl),
- argThat(h -> (h.inputConfig & InputConfig.SENSITIVE_FOR_TRACING) != 0));
+ argThat(h -> (h.inputConfig & InputConfig.SENSITIVE_FOR_PRIVACY) != 0));
}
@RequiresFlagsDisabled(Flags.FLAG_ALWAYS_DRAW_MAGNIFICATION_FULLSCREEN_BORDER)
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 9acda5f..e8bac66 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -37,6 +37,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.res.Resources;
@@ -62,6 +63,7 @@
import android.os.FileUtils;
import android.os.Handler;
import android.os.HwBinder;
+import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.ParcelFileDescriptor;
@@ -89,6 +91,7 @@
import com.android.internal.util.dump.DualDumpOutputStream;
import com.android.server.FgThread;
import com.android.server.LocalServices;
+import com.android.server.usb.flags.Flags;
import com.android.server.usb.hal.gadget.UsbGadgetHal;
import com.android.server.usb.hal.gadget.UsbGadgetHalInstance;
import com.android.server.utils.EventLogger;
@@ -586,6 +589,22 @@
*/
protected static final String USB_PERSISTENT_CONFIG_PROPERTY = "persist.sys.usb.config";
+ protected static final String MTP_PACKAGE_NAME = "com.android.mtp";
+ protected static final String MTP_SERVICE_CLASS_NAME = "com.android.mtp.MtpService";
+
+ private boolean mIsMtpServiceBound = false;
+
+ /**
+ * {@link ServiceConnection} for {@link MtpService}.
+ */
+ private ServiceConnection mMtpServiceConnection = new ServiceConnection() {
+ @Override
+ public void onServiceConnected(ComponentName className, IBinder service) {}
+
+ @Override
+ public void onServiceDisconnected(ComponentName arg0) {}
+ };
+
UsbHandler(Looper looper, Context context, UsbDeviceManager deviceManager,
UsbAlsaManager alsaManager, UsbPermissionManager permissionManager) {
super(looper);
@@ -915,6 +934,7 @@
private void updateUsbFunctions() {
updateMidiFunction();
+ updateMtpFunction();
}
private void updateMidiFunction() {
@@ -941,6 +961,67 @@
mMidiEnabled && mConfigured, mMidiCard, mMidiDevice);
}
+ /**
+ * Bind to MtpService when MTP or PTP is enabled. This is done to prevent activity manager
+ * from freezing the corresponding process.
+ */
+ private void updateMtpFunction() {
+ if (!Flags.enableBindToMtpService()) {
+ return;
+ }
+
+ boolean mtpEnabled = ((mCurrentFunctions & UsbManager.FUNCTION_MTP) != 0);
+ boolean ptpEnabled = ((mCurrentFunctions & UsbManager.FUNCTION_PTP) != 0);
+
+ if (DEBUG) {
+ Slog.d(TAG, "updateMtpFunction "
+ + ", mtpEnabled: " + mtpEnabled
+ + ", ptpEnabled: " + ptpEnabled
+ + ", mIsMtpServiceBound: " + mIsMtpServiceBound
+ );
+ }
+
+ if (mConfigured && (mtpEnabled || ptpEnabled)) {
+ bindToMtpService();
+ } else if (mIsMtpServiceBound) {
+ unbindMtpService();
+ }
+ }
+
+ private void bindToMtpService() {
+ Intent intent = new Intent();
+ intent.setComponent(new ComponentName(MTP_PACKAGE_NAME, MTP_SERVICE_CLASS_NAME));
+
+ if (DEBUG) Slog.d(TAG, "Binding to MtpService");
+
+ try {
+ mIsMtpServiceBound = mContext.bindServiceAsUser(
+ intent,
+ mMtpServiceConnection,
+ Context.BIND_AUTO_CREATE,
+ UserHandle.CURRENT
+ );
+ } catch (SecurityException exception) {
+ Slog.e(TAG, "Unable to bind to MtpService due to SecurityException", exception);
+ }
+
+ // Unbinding from the service if binding was not successful to release the connection.
+ // https://developer.android.com/reference/android/content/Context#bindService(android.content.Intent,%20android.content.ServiceConnection,%20int)
+ if (!mIsMtpServiceBound) {
+ unbindMtpService();
+ Slog.e(TAG, "Binding to MtpService failed");
+ }
+
+ if (DEBUG && mIsMtpServiceBound) Slog.d(TAG, "Successfully bound to MtpService");
+ }
+
+ private void unbindMtpService() {
+ if (DEBUG) Slog.d(TAG, "Unbinding from MtpService");
+
+ mContext.unbindService(mMtpServiceConnection);
+ mIsMtpServiceBound = false;
+ }
+
private void setScreenUnlockedFunctions(int operationId) {
setEnabledFunctions(mScreenUnlockedFunctions, false, operationId);
}
diff --git a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
index 40537c8..6d53c27 100644
--- a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
+++ b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
@@ -16,6 +16,8 @@
package com.android.server.usb;
+import static android.provider.Settings.Secure.USER_SETUP_COMPLETE;
+
import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_MANAGED_PROFILE;
import android.Manifest;
@@ -43,6 +45,7 @@
import android.os.Environment;
import android.os.UserHandle;
import android.os.UserManager;
+import android.provider.Settings;
import android.service.usb.UsbProfileGroupSettingsManagerProto;
import android.service.usb.UsbSettingsAccessoryPreferenceProto;
import android.service.usb.UsbSettingsDevicePreferenceProto;
@@ -939,13 +942,24 @@
}
/**
- * @return true if any application in foreground have set restrict_usb_overlay_activities as
- * true in manifest file. The application needs to have MANAGE_USB permission.
+ * @return true if the user has not finished the setup process or if there are any
+ * foreground applications with MANAGE_USB permission and restrict_usb_overlay_activities
+ * enabled in the manifest file.
*/
private boolean shouldRestrictOverlayActivities() {
if (!Flags.allowRestrictionOfOverlayActivities()) return false;
+ if (Settings.Secure.getIntForUser(
+ mContext.getContentResolver(),
+ USER_SETUP_COMPLETE,
+ /* defaultValue= */ 1,
+ UserHandle.CURRENT.getIdentifier())
+ == 0) {
+ Slog.d(TAG, "restricting usb overlay activities as setup is not complete");
+ return true;
+ }
+
List<ActivityManager.RunningAppProcessInfo> appProcessInfos = mActivityManager
.getRunningAppProcesses();
diff --git a/services/usb/java/com/android/server/usb/flags/usb_flags.aconfig b/services/usb/java/com/android/server/usb/flags/usb_flags.aconfig
index a7c5ddb..cd96d76 100644
--- a/services/usb/java/com/android/server/usb/flags/usb_flags.aconfig
+++ b/services/usb/java/com/android/server/usb/flags/usb_flags.aconfig
@@ -7,3 +7,10 @@
description: "This flag controls the restriction of usb overlay activities"
bug: "307231174"
}
+
+flag {
+ name: "enable_bind_to_mtp_service"
+ namespace: "usb"
+ description: "This flag enables binding to MtpService when in mtp/ptp modes"
+ bug: "332256525"
+}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index e5d7b40e..1d01420 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -2538,7 +2538,8 @@
}
}
- PackageMonitor mPackageMonitor = new PackageMonitor() {
+ PackageMonitor mPackageMonitor = new PackageMonitor(
+ /* supportsPackageRestartQuery= */ true) {
@Override
public boolean onHandleForceStop(Intent intent, String[] packages, int uid,
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 7db4180..bc8f65e 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -3888,7 +3888,7 @@
/**
* Whether device resets all of NR timers when device is in a voice call and QOS is established.
- * The default value is false;
+ * The default value is true;
*
* @see #KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING
* @see #KEY_5G_ICON_DISPLAY_SECONDARY_GRACE_PERIOD_STRING
@@ -6007,7 +6007,7 @@
defaults.putBoolean(KEY_ENABLE_PRESENCE_CAPABILITY_EXCHANGE_BOOL, false);
defaults.putBoolean(KEY_RCS_BULK_CAPABILITY_EXCHANGE_BOOL, false);
defaults.putBoolean(KEY_ENABLE_PRESENCE_GROUP_SUBSCRIBE_BOOL, false);
- defaults.putInt(KEY_SUBSCRIBE_RETRY_DURATION_MILLIS_LONG, -1);
+ defaults.putLong(KEY_SUBSCRIBE_RETRY_DURATION_MILLIS_LONG, -1);
defaults.putBoolean(KEY_USE_SIP_URI_FOR_PRESENCE_SUBSCRIBE_BOOL, false);
defaults.putInt(KEY_NON_RCS_CAPABILITIES_CACHE_EXPIRATION_SEC_INT, 30 * 24 * 60 * 60);
defaults.putBoolean(KEY_RCS_REQUEST_FORBIDDEN_BY_SIP_489_BOOL, false);
@@ -10909,7 +10909,7 @@
sDefaults.putString(KEY_5G_ICON_DISPLAY_SECONDARY_GRACE_PERIOD_STRING, "");
sDefaults.putInt(KEY_NR_ADVANCED_BANDS_SECONDARY_TIMER_SECONDS_INT, 0);
sDefaults.putBoolean(KEY_NR_TIMERS_RESET_IF_NON_ENDC_AND_RRC_IDLE_BOOL, false);
- sDefaults.putBoolean(KEY_NR_TIMERS_RESET_ON_VOICE_QOS_BOOL, false);
+ sDefaults.putBoolean(KEY_NR_TIMERS_RESET_ON_VOICE_QOS_BOOL, true);
sDefaults.putBoolean(KEY_NR_TIMERS_RESET_ON_PLMN_CHANGE_BOOL, false);
/* Default value is 1 hour. */
sDefaults.putLong(KEY_5G_WATCHDOG_TIME_MS_LONG, 3600000);
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index f161f31..0ecafc7 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -1283,6 +1283,8 @@
private static final String JAPAN_ISO_COUNTRY_CODE = "JP";
+ private static final String SINGAPORE_ISO_COUNTRY_CODE = "SG";
+
/**
* Breaks the given number down and formats it according to the rules
* for the country the number is from.
@@ -1669,6 +1671,17 @@
* dialing format.
*/
result = util.format(pn, PhoneNumberUtil.PhoneNumberFormat.NATIONAL);
+ } else if (Flags.removeCountryCodeFromLocalSingaporeCalls() &&
+ (SINGAPORE_ISO_COUNTRY_CODE.equalsIgnoreCase(defaultCountryIso) &&
+ pn.getCountryCode() ==
+ util.getCountryCodeForRegion(SINGAPORE_ISO_COUNTRY_CODE) &&
+ (pn.getCountryCodeSource() ==
+ PhoneNumber.CountryCodeSource.FROM_NUMBER_WITH_PLUS_SIGN))) {
+ /*
+ * Need to reformat Singaporean phone numbers (when the user is in Singapore)
+ * with the country code (+65) removed to comply with Singaporean regulations.
+ */
+ result = util.format(pn, PhoneNumberUtil.PhoneNumberFormat.NATIONAL);
} else {
result = util.formatInOriginalFormat(pn, defaultCountryIso);
}
diff --git a/telephony/java/android/telephony/PreciseDataConnectionState.java b/telephony/java/android/telephony/PreciseDataConnectionState.java
index b568f07..e6515f13 100644
--- a/telephony/java/android/telephony/PreciseDataConnectionState.java
+++ b/telephony/java/android/telephony/PreciseDataConnectionState.java
@@ -65,6 +65,7 @@
public final class PreciseDataConnectionState implements Parcelable {
private final @TransportType int mTransportType;
private final int mId;
+ private final int mNetId;
private final @DataState int mState;
private final @NetworkType int mNetworkType;
private final @DataFailureCause int mFailCause;
@@ -134,7 +135,7 @@
@ApnType int apnTypes, @NonNull String apn,
@Nullable LinkProperties linkProperties,
@DataFailureCause int failCause) {
- this(AccessNetworkConstants.TRANSPORT_TYPE_INVALID, -1, state, networkType,
+ this(AccessNetworkConstants.TRANSPORT_TYPE_INVALID, -1, -1, state, networkType,
linkProperties, failCause, new ApnSetting.Builder()
.setApnTypeBitmask(apnTypes)
.setApnName(apn)
@@ -158,13 +159,14 @@
* @param defaultQos If there is a valid QoS for the default bearer supporting this data call,
* (supported for LTE and NR), then this is specified. Otherwise it should be null.
*/
- private PreciseDataConnectionState(@TransportType int transportType, int id,
+ private PreciseDataConnectionState(@TransportType int transportType, int id, int netId,
@DataState int state, @NetworkType int networkType,
@Nullable LinkProperties linkProperties, @DataFailureCause int failCause,
@Nullable ApnSetting apnSetting, @Nullable Qos defaultQos,
@NetworkValidationStatus int networkValidationStatus) {
mTransportType = transportType;
mId = id;
+ mNetId = netId;
mState = state;
mNetworkType = networkType;
mLinkProperties = linkProperties;
@@ -182,6 +184,7 @@
private PreciseDataConnectionState(Parcel in) {
mTransportType = in.readInt();
mId = in.readInt();
+ mNetId = in.readInt();
mState = in.readInt();
mNetworkType = in.readInt();
mLinkProperties = in.readParcelable(
@@ -244,6 +247,14 @@
}
/**
+ * @return the current TelephonyNetworkAgent ID. {@code -1} if no network agent.
+ * @hide
+ */
+ public int getNetId() {
+ return mNetId;
+ }
+
+ /**
* @return The high-level state of this data connection.
*/
public @DataState int getState() {
@@ -363,6 +374,7 @@
public void writeToParcel(@NonNull Parcel out, int flags) {
out.writeInt(mTransportType);
out.writeInt(mId);
+ out.writeInt(mNetId);
out.writeInt(mState);
out.writeInt(mNetworkType);
out.writeParcelable(mLinkProperties, flags);
@@ -386,7 +398,7 @@
@Override
public int hashCode() {
- return Objects.hash(mTransportType, mId, mState, mNetworkType, mFailCause,
+ return Objects.hash(mTransportType, mId, mNetId, mState, mNetworkType, mFailCause,
mLinkProperties, mApnSetting, mDefaultQos, mNetworkValidationStatus);
}
@@ -398,6 +410,7 @@
PreciseDataConnectionState that = (PreciseDataConnectionState) o;
return mTransportType == that.mTransportType
&& mId == that.mId
+ && mNetId == that.mNetId
&& mState == that.mState
&& mNetworkType == that.mNetworkType
&& mFailCause == that.mFailCause
@@ -412,17 +425,18 @@
public String toString() {
StringBuilder sb = new StringBuilder();
- sb.append(" state: " + TelephonyUtils.dataStateToString(mState));
- sb.append(", transport: "
- + AccessNetworkConstants.transportTypeToString(mTransportType));
- sb.append(", id: " + mId);
- sb.append(", network type: " + TelephonyManager.getNetworkTypeName(mNetworkType));
- sb.append(", APN Setting: " + mApnSetting);
- sb.append(", link properties: " + mLinkProperties);
- sb.append(", default QoS: " + mDefaultQos);
- sb.append(", fail cause: " + DataFailCause.toString(mFailCause));
- sb.append(", network validation status: "
- + networkValidationStatusToString(mNetworkValidationStatus));
+ sb.append(" state: ").append(TelephonyUtils.dataStateToString(mState));
+ sb.append(", transport: ").append(
+ AccessNetworkConstants.transportTypeToString(mTransportType));
+ sb.append(", id: ").append(mId);
+ sb.append(", netId: ").append(mNetId);
+ sb.append(", network type: ").append(TelephonyManager.getNetworkTypeName(mNetworkType));
+ sb.append(", APN Setting: ").append(mApnSetting);
+ sb.append(", link properties: ").append(mLinkProperties);
+ sb.append(", default QoS: ").append(mDefaultQos);
+ sb.append(", fail cause: ").append(DataFailCause.toString(mFailCause));
+ sb.append(", network validation status: ").append(
+ networkValidationStatusToString(mNetworkValidationStatus));
return sb.toString();
}
@@ -463,6 +477,11 @@
*/
private int mId = -1;
+ /**
+ * The current TelephonyNetworkAgent ID. {@code -1} if no network agent.
+ */
+ private int mNetworkAgentId = -1;
+
/** The state of the data connection */
private @DataState int mState = TelephonyManager.DATA_UNKNOWN;
@@ -511,6 +530,17 @@
}
/**
+ * Set the id of the data connection.
+ *
+ * @param agentId The id of the data connection
+ * @return The builder
+ */
+ public @NonNull Builder setNetworkAgentId(int agentId) {
+ mNetworkAgentId = agentId;
+ return this;
+ }
+
+ /**
* Set the state of the data connection.
*
* @param state The state of the data connection
@@ -598,8 +628,8 @@
* @return The {@link PreciseDataConnectionState} instance
*/
public PreciseDataConnectionState build() {
- return new PreciseDataConnectionState(mTransportType, mId, mState, mNetworkType,
- mLinkProperties, mFailCause, mApnSetting, mDefaultQos,
+ return new PreciseDataConnectionState(mTransportType, mId, mNetworkAgentId, mState,
+ mNetworkType, mLinkProperties, mFailCause, mApnSetting, mDefaultQos,
mNetworkValidationStatus);
}
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index f076de3..03ba8fa 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -13787,11 +13787,11 @@
* <p>This method returns valid data on devices with {@link
* android.content.pm.PackageManager#FEATURE_TELEPHONY_CARRIERLOCK} enabled.
*
- * @deprecated Apps should use {@link getCarriersRestrictionRules} to retrieve the list of
+ * @deprecated Apps should use {@link #getCarrierRestrictionRules} to retrieve the list of
* allowed and excliuded carriers, as the result of this API is valid only when the excluded
* list is empty. This API could return an empty list, even if some restrictions are present.
*
- * @return List of {@link android.telephony.CarrierIdentifier}; empty list
+ * @return List of {@link android.service.carrier.CarrierIdentifier}; empty list
* means all carriers are allowed.
*
* @throws UnsupportedOperationException If the device does not have
@@ -19266,6 +19266,26 @@
}
/**
+ * Returns whether the AOSP domain selection service is supported.
+ *
+ * @return {@code true} if the AOSP domain selection service is supported.
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
+ public boolean isAospDomainSelectionService() {
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ return telephony.isAospDomainSelectionService();
+ }
+ } catch (RemoteException ex) {
+ Rlog.w(TAG, "RemoteException", ex);
+ }
+ return false;
+ }
+
+ /**
* Returns the primary IMEI (International Mobile Equipment Identity) of the device as
* mentioned in GSMA TS.37. {@link #getImei(int)} returns the IMEI that belongs to the selected
* slotID whereas this API {@link #getPrimaryImei()} returns primary IMEI of the device.
diff --git a/telephony/java/android/telephony/satellite/ISatelliteCommunicationAllowedStateCallback.aidl b/telephony/java/android/telephony/satellite/ISatelliteCommunicationAllowedStateCallback.aidl
new file mode 100644
index 0000000..a7eda48
--- /dev/null
+++ b/telephony/java/android/telephony/satellite/ISatelliteCommunicationAllowedStateCallback.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony.satellite;
+
+/**
+ * Interface for satellite communication allowed state callback.
+ * @hide
+ */
+oneway interface ISatelliteCommunicationAllowedStateCallback {
+ /**
+ * Telephony does not guarantee that whenever there is a change in communication allowed
+ * state, this API will be called. Telephony does its best to detect the changes and notify
+ * its listners accordingly.
+ *
+ * @param allowed whether satellite communication state or not
+ */
+ void onSatelliteCommunicationAllowedStateChanged(in boolean isAllowed);
+}
diff --git a/telephony/java/android/telephony/satellite/SatelliteCommunicationAllowedStateCallback.java b/telephony/java/android/telephony/satellite/SatelliteCommunicationAllowedStateCallback.java
new file mode 100644
index 0000000..1a87020
--- /dev/null
+++ b/telephony/java/android/telephony/satellite/SatelliteCommunicationAllowedStateCallback.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony.satellite;
+
+import android.annotation.FlaggedApi;
+
+import com.android.internal.telephony.flags.Flags;
+
+
+/**
+ * A callback class for monitoring satellite communication allowed state changed events.
+ *
+ * @hide
+ */
+@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
+public interface SatelliteCommunicationAllowedStateCallback {
+
+ /**
+ * Telephony does not guarantee that whenever there is a change in communication allowed state,
+ * this API will be called. Telephony does its best to detect the changes and notify its
+ * listeners accordingly.
+ *
+ * @param isAllowed {@code true} means satellite allow state is changed,
+ * {@code false} satellite allow state is not changed
+ * @hide
+ */
+ @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
+ void onSatelliteCommunicationAllowedStateChanged(boolean isAllowed);
+}
diff --git a/telephony/java/android/telephony/satellite/SatelliteManager.java b/telephony/java/android/telephony/satellite/SatelliteManager.java
index 40ad312..0bb5fd5 100644
--- a/telephony/java/android/telephony/satellite/SatelliteManager.java
+++ b/telephony/java/android/telephony/satellite/SatelliteManager.java
@@ -91,6 +91,11 @@
ISatelliteSupportedStateCallback> sSatelliteSupportedStateCallbackMap =
new ConcurrentHashMap<>();
+ private static final ConcurrentHashMap<SatelliteCommunicationAllowedStateCallback,
+ ISatelliteCommunicationAllowedStateCallback>
+ sSatelliteCommunicationAllowedStateCallbackMap =
+ new ConcurrentHashMap<>();
+
private final int mSubId;
/**
@@ -2393,7 +2398,89 @@
}
}
- @Nullable private static ITelephony getITelephony() {
+ /**
+ * Registers for the satellite communication allowed state changed.
+ *
+ * @param executor The executor on which the callback will be called.
+ * @param callback The callback to handle satellite communication allowed state changed event.
+ * @return The {@link SatelliteResult} result of the operation.
+ * @throws SecurityException if the caller doesn't have required permission.
+ * @throws IllegalStateException if the Telephony process is not currently available.
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
+ @SatelliteResult
+ public int registerForCommunicationAllowedStateChanged(
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull SatelliteCommunicationAllowedStateCallback callback) {
+ Objects.requireNonNull(executor);
+ Objects.requireNonNull(callback);
+
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ ISatelliteCommunicationAllowedStateCallback internalCallback =
+ new ISatelliteCommunicationAllowedStateCallback.Stub() {
+ @Override
+ public void onSatelliteCommunicationAllowedStateChanged(
+ boolean isAllowed) {
+ executor.execute(() -> Binder.withCleanCallingIdentity(
+ () -> callback.onSatelliteCommunicationAllowedStateChanged(
+ isAllowed)));
+ }
+ };
+ sSatelliteCommunicationAllowedStateCallbackMap.put(callback, internalCallback);
+ return telephony.registerForCommunicationAllowedStateChanged(
+ mSubId, internalCallback);
+ } else {
+ throw new IllegalStateException("telephony service is null.");
+ }
+ } catch (RemoteException ex) {
+ loge("registerForCommunicationAllowedStateChanged() RemoteException: " + ex);
+ ex.rethrowAsRuntimeException();
+ }
+ return SATELLITE_RESULT_REQUEST_FAILED;
+ }
+
+ /**
+ * Unregisters for the satellite communication allowed state changed.
+ * If callback was not registered before, the request will be ignored.
+ *
+ * @param callback The callback that was passed to
+ * {@link #registerForCommunicationAllowedStateChanged(Executor,
+ * SatelliteCommunicationAllowedStateCallback)}
+ * @throws SecurityException if the caller doesn't have required permission.
+ * @throws IllegalStateException if the Telephony process is not currently available.
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
+ @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
+ public void unregisterForCommunicationAllowedStateChanged(
+ @NonNull SatelliteCommunicationAllowedStateCallback callback) {
+ Objects.requireNonNull(callback);
+ ISatelliteCommunicationAllowedStateCallback internalCallback =
+ sSatelliteCommunicationAllowedStateCallbackMap.remove(callback);
+
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ if (internalCallback != null) {
+ telephony.unregisterForCommunicationAllowedStateChanged(mSubId,
+ internalCallback);
+ } else {
+ loge("unregisterForCommunicationAllowedStateChanged: No internal callback.");
+ }
+ } else {
+ throw new IllegalStateException("telephony service is null.");
+ }
+ } catch (RemoteException ex) {
+ loge("unregisterForCommunicationAllowedStateChanged() RemoteException: " + ex);
+ ex.rethrowAsRuntimeException();
+ }
+ }
+
+ @Nullable
+ private static ITelephony getITelephony() {
ITelephony binder = ITelephony.Stub.asInterface(TelephonyFrameworkInitializer
.getTelephonyServiceManager()
.getTelephonyServiceRegisterer()
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index f25fc36..d4da736 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -69,6 +69,7 @@
import android.telephony.ims.aidl.IRcsConfigCallback;
import android.telephony.satellite.INtnSignalStrengthCallback;
import android.telephony.satellite.ISatelliteCapabilitiesCallback;
+import android.telephony.satellite.ISatelliteCommunicationAllowedStateCallback;
import android.telephony.satellite.ISatelliteDatagramCallback;
import android.telephony.satellite.ISatelliteTransmissionUpdateCallback;
import android.telephony.satellite.ISatelliteProvisionStateCallback;
@@ -3244,6 +3245,12 @@
boolean clearDomainSelectionServiceOverride();
/**
+ * @return {@code true} if the AOSP domain selection service is supported,
+ * {@code false} otherwise.
+ */
+ boolean isAospDomainSelectionService();
+
+ /**
* Enable or disable notifications sent for cellular identifier disclosure events.
*
* Disclosure events are defined as instances where a device has sent a cellular identifier
@@ -3341,4 +3348,29 @@
+ "android.Manifest.permission.SATELLITE_COMMUNICATION)")
void unregisterForSatelliteSupportedStateChanged(int subId,
in ISatelliteSupportedStateCallback callback);
+
+ /**
+ * Registers for satellite communication allowed state changed.
+ *
+ * @param subId The subId of the subscription to register for communication allowed state.
+ * @param callback The callback to handle the communication allowed state changed event.
+ *
+ * @return The {@link SatelliteError} result of the operation.
+ */
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission("
+ + "android.Manifest.permission.SATELLITE_COMMUNICATION)")
+ int registerForCommunicationAllowedStateChanged(int subId,
+ in ISatelliteCommunicationAllowedStateCallback callback);
+
+ /**
+ * Unregisters for satellite communication allowed state.
+ * If callback was not registered before, the request will be ignored.
+ *
+ * @param subId The subId of the subscription to unregister for supported state changed.
+ * @param callback The callback that was passed to registerForCommunicationAllowedStateChanged.
+ */
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission("
+ + "android.Manifest.permission.SATELLITE_COMMUNICATION)")
+ void unregisterForCommunicationAllowedStateChanged(int subId,
+ in ISatelliteCommunicationAllowedStateCallback callback);
}
diff --git a/tests/FlickerTests/IME/OWNERS b/tests/FlickerTests/IME/OWNERS
index 301fafa..ae1098d 100644
--- a/tests/FlickerTests/IME/OWNERS
+++ b/tests/FlickerTests/IME/OWNERS
@@ -1,2 +1,3 @@
# ime
# Bug component: 34867
+include /services/core/java/com/android/server/inputmethod/OWNERS
diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnUnlockScreenTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnUnlockScreenTest.kt
index 31506b5..d22bdcf 100644
--- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnUnlockScreenTest.kt
+++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnUnlockScreenTest.kt
@@ -24,6 +24,7 @@
import android.tools.flicker.legacy.LegacyFlickerTest
import android.tools.flicker.legacy.LegacyFlickerTestFactory
import android.tools.traces.component.ComponentNameMatcher
+import androidx.test.filters.FlakyTest
import com.android.server.wm.flicker.BaseTest
import com.android.server.wm.flicker.helpers.ImeAppHelper
import org.junit.FixMethodOrder
@@ -90,6 +91,11 @@
@Ignore("Not applicable to this CUJ. Display turns off during transition")
override fun taskBarWindowIsAlwaysVisible() {}
+ @FlakyTest(bugId = 338178020)
+ @Test
+ override fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
+ super.visibleWindowsShownMoreThanOneConsecutiveEntry()
+
companion object {
@Parameterized.Parameters(name = "{0}")
@JvmStatic
diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityEmbeddingMainActivity.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityEmbeddingMainActivity.java
index 23fa91c..2df3da6 100644
--- a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityEmbeddingMainActivity.java
+++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityEmbeddingMainActivity.java
@@ -16,7 +16,6 @@
package com.android.server.wm.flicker.testapp;
-import androidx.annotation.NonNull;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
@@ -103,18 +102,13 @@
}
private static SplitPairRule createSplitPairRules(@NonNull String layoutDirection) {
- final Set<SplitPairFilter> pairFilters = new HashSet<>();
- final SplitPairFilter activitiesPair = new SplitPairFilter(
- ActivityOptions.ActivityEmbedding.MainActivity.COMPONENT,
- ActivityOptions.ActivityEmbedding.SecondaryActivity.COMPONENT,
- null /* secondaryActivityIntentAction */);
- pairFilters.add(activitiesPair);
+ final Set<SplitPairFilter> pairFilters = getSplitPairFilters();
final SplitAttributes splitAttributes = new SplitAttributes.Builder()
.setSplitType(SplitAttributes.SplitType.SPLIT_TYPE_EQUAL)
.setLayoutDirection(parseLayoutDirection(layoutDirection))
.build();
// Setting thresholds to ALWAYS_ALLOW values to make it easy for running on all devices.
- final SplitPairRule rule = new SplitPairRule.Builder(pairFilters)
+ return new SplitPairRule.Builder(pairFilters)
.setDefaultSplitAttributes(splitAttributes)
.setMinWidthDp(SplitRule.SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
.setMinHeightDp(SplitRule.SPLIT_MIN_DIMENSION_ALWAYS_ALLOW)
@@ -122,7 +116,22 @@
.setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ALWAYS_ALLOW)
.setMaxAspectRatioInLandscape(EmbeddingAspectRatio.ALWAYS_ALLOW)
.build();
- return rule;
+ }
+
+ @NonNull
+ private static Set<SplitPairFilter> getSplitPairFilters() {
+ final Set<SplitPairFilter> pairFilters = new HashSet<>();
+ final SplitPairFilter mainAndSecondaryActivitiesPair = new SplitPairFilter(
+ ActivityOptions.ActivityEmbedding.MainActivity.COMPONENT,
+ ActivityOptions.ActivityEmbedding.SecondaryActivity.COMPONENT,
+ null /* secondaryActivityIntentAction */);
+ pairFilters.add(mainAndSecondaryActivitiesPair);
+ final SplitPairFilter mainAndTrampolineActivitiesPair = new SplitPairFilter(
+ ActivityOptions.ActivityEmbedding.MainActivity.COMPONENT,
+ ActivityOptions.ActivityEmbedding.TrampolineActivity.COMPONENT,
+ null /* secondaryActivityIntentAction */);
+ pairFilters.add(mainAndTrampolineActivitiesPair);
+ return pairFilters;
}
private static SplitPlaceholderRule createSplitPlaceholderRules(
diff --git a/tests/Input/Android.bp b/tests/Input/Android.bp
index d17cd1f..a85d809 100644
--- a/tests/Input/Android.bp
+++ b/tests/Input/Android.bp
@@ -30,7 +30,7 @@
"androidx.test.rules",
"androidx.test.runner",
"androidx.test.uiautomator_uiautomator",
- "servicestests-utils",
+ "compatibility-device-util-axt",
"flag-junit",
"frameworks-base-testutils",
"hamcrest-library",
@@ -38,6 +38,7 @@
"mockito-target-minus-junit4",
"platform-test-annotations",
"services.core.unboosted",
+ "servicestests-utils",
"testables",
"testng",
"truth",
diff --git a/tests/Input/src/com/android/server/input/InputManagerServiceTests.kt b/tests/Input/src/com/android/server/input/InputManagerServiceTests.kt
index c9c6574..0fc9d6f 100644
--- a/tests/Input/src/com/android/server/input/InputManagerServiceTests.kt
+++ b/tests/Input/src/com/android/server/input/InputManagerServiceTests.kt
@@ -42,6 +42,7 @@
import androidx.test.platform.app.InstrumentationRegistry
import com.android.internal.util.test.FakeSettingsProvider
import com.google.common.truth.Truth.assertThat
+import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
import org.junit.After
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
@@ -151,7 +152,9 @@
fun testInputSettingsUpdatedOnSystemRunning() {
verifyZeroInteractions(native)
- service.systemRunning()
+ runWithShellPermissionIdentity {
+ service.systemRunning()
+ }
verify(native).setPointerSpeed(anyInt())
verify(native).setTouchpadPointerSpeed(anyInt())
diff --git a/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/ImeStressTestUtil.java b/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/ImeStressTestUtil.java
index c0c60ef..d033389 100644
--- a/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/ImeStressTestUtil.java
+++ b/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/ImeStressTestUtil.java
@@ -393,6 +393,7 @@
mEditText.setFocusableInTouchMode(false);
}
rootView.addView(mEditText, new LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT));
+ rootView.setFitsSystemWindows(true);
setContentView(rootView);
if (requestFocus) {
diff --git a/tests/UsbManagerTests/Android.bp b/tests/UsbManagerTests/Android.bp
index f0bea3f..2909e66 100644
--- a/tests/UsbManagerTests/Android.bp
+++ b/tests/UsbManagerTests/Android.bp
@@ -43,6 +43,9 @@
"libmultiplejvmtiagentsinterferenceagent",
"libstaticjvmtiagent",
],
+ libs: [
+ "android.test.mock",
+ ],
certificate: "platform",
platform_apis: true,
test_suites: ["device-tests"],
diff --git a/tests/UsbManagerTests/src/com/android/server/usbtest/UsbProfileGroupSettingsManagerTest.java b/tests/UsbManagerTests/src/com/android/server/usbtest/UsbProfileGroupSettingsManagerTest.java
index 4780d8a..87b26a6 100644
--- a/tests/UsbManagerTests/src/com/android/server/usbtest/UsbProfileGroupSettingsManagerTest.java
+++ b/tests/UsbManagerTests/src/com/android/server/usbtest/UsbProfileGroupSettingsManagerTest.java
@@ -16,6 +16,8 @@
package com.android.server.usbtest;
+import static android.provider.Settings.Secure.USER_SETUP_COMPLETE;
+
import static com.android.server.usb.UsbProfileGroupSettingsManager.PROPERTY_RESTRICT_USB_OVERLAY_ACTIVITIES;
import static org.mockito.ArgumentMatchers.any;
@@ -32,16 +34,20 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PackageManager.Property;
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.hardware.usb.UsbDevice;
import android.os.UserHandle;
import android.os.UserManager;
+import android.provider.Settings;
+import android.test.mock.MockContentResolver;
import androidx.test.runner.AndroidJUnit4;
import com.android.dx.mockito.inline.extended.ExtendedMockito;
+import com.android.internal.util.test.FakeSettingsProvider;
import com.android.server.usb.UsbHandlerManager;
import com.android.server.usb.UsbProfileGroupSettingsManager;
import com.android.server.usb.UsbSettingsManager;
@@ -69,6 +75,7 @@
public class UsbProfileGroupSettingsManagerTest {
private static final String TEST_PACKAGE_NAME = "testPkg";
+
@Mock
private Context mContext;
@Mock
@@ -85,43 +92,78 @@
private UserManager mUserManager;
@Mock
private UsbUserSettingsManager mUsbUserSettingsManager;
- @Mock private Property mProperty;
- private ActivityManager.RunningAppProcessInfo mRunningAppProcessInfo;
- private PackageInfo mPackageInfo;
- private UsbProfileGroupSettingsManager mUsbProfileGroupSettingsManager;
+ @Mock
+ private Property mRestrictUsbOverlayActivitiesProperty;
+ @Mock
+ private UsbDevice mUsbDevice;
+
+ private MockContentResolver mContentResolver;
private MockitoSession mStaticMockSession;
+ private UsbProfileGroupSettingsManager mUsbProfileGroupSettingsManager;
+
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
-
- mRunningAppProcessInfo = new ActivityManager.RunningAppProcessInfo();
- mRunningAppProcessInfo.pkgList = new String[]{TEST_PACKAGE_NAME};
- mPackageInfo = new PackageInfo();
- mPackageInfo.packageName = TEST_PACKAGE_NAME;
- mPackageInfo.applicationInfo = Mockito.mock(ApplicationInfo.class);
-
- when(mContext.getPackageManager()).thenReturn(mPackageManager);
- when(mContext.getSystemService(ActivityManager.class)).thenReturn(mActivityManager);
- when(mContext.getResources()).thenReturn(Mockito.mock(Resources.class));
- when(mContext.createPackageContextAsUser(anyString(), anyInt(), any(UserHandle.class)))
- .thenReturn(mContext);
- when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
-
- mUsbProfileGroupSettingsManager = new UsbProfileGroupSettingsManager(mContext, mUserHandle,
- mUsbSettingsManager, mUsbHandlerManager);
-
mStaticMockSession = ExtendedMockito.mockitoSession()
.mockStatic(Flags.class)
.strictness(Strictness.WARN)
.startMocking();
- when(mPackageManager.getPackageInfo(TEST_PACKAGE_NAME, 0)).thenReturn(mPackageInfo);
- when(mPackageManager.getProperty(eq(PROPERTY_RESTRICT_USB_OVERLAY_ACTIVITIES),
- eq(TEST_PACKAGE_NAME))).thenReturn(mProperty);
+ when(mUsbSettingsManager.getSettingsForUser(anyInt())).thenReturn(mUsbUserSettingsManager);
when(mUserManager.getEnabledProfiles(anyInt()))
.thenReturn(List.of(Mockito.mock(UserInfo.class)));
- when(mUsbSettingsManager.getSettingsForUser(anyInt())).thenReturn(mUsbUserSettingsManager);
+
+ mContentResolver = new MockContentResolver();
+ mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
+
+ when(mContext.getContentResolver()).thenReturn(mContentResolver);
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
+ when(mContext.getResources()).thenReturn(Mockito.mock(Resources.class));
+ when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
+ when(mContext.getSystemService(ActivityManager.class)).thenReturn(mActivityManager);
+ when(mContext.createPackageContextAsUser(anyString(), anyInt(), any(UserHandle.class)))
+ .thenReturn(mContext);
+
+ mUsbProfileGroupSettingsManager = new UsbProfileGroupSettingsManager(
+ mContext, mUserHandle, mUsbSettingsManager, mUsbHandlerManager);
+
+ setupDefaultConfiguration();
+ }
+
+ /**
+ * Setups the following configuration
+ *
+ * <ul>
+ * <li>Flag is enabled
+ * <li>Device setup has completed
+ * <li>There is a foreground activity with MANAGE_USB permission
+ * <li>The foreground activity has PROPERTY_RESTRICT_USB_OVERLAY_ACTIVITIES enabled
+ * </ul>
+ */
+ private void setupDefaultConfiguration() throws NameNotFoundException {
+ when(Flags.allowRestrictionOfOverlayActivities()).thenReturn(true);
+
+ Settings.Secure.putInt(mContentResolver, USER_SETUP_COMPLETE, 1);
+
+ ActivityManager.RunningAppProcessInfo mRunningAppProcessInfo =
+ new ActivityManager.RunningAppProcessInfo();
+ mRunningAppProcessInfo.pkgList = new String[] { TEST_PACKAGE_NAME };
+ when(mActivityManager.getRunningAppProcesses()).thenReturn(List.of(mRunningAppProcessInfo));
+
+ PackageInfo mPackageInfo = new PackageInfo();
+ mPackageInfo.packageName = TEST_PACKAGE_NAME;
+ mPackageInfo.applicationInfo = Mockito.mock(ApplicationInfo.class);
+ when(mPackageManager.getPackageInfo(TEST_PACKAGE_NAME, 0)).thenReturn(mPackageInfo);
+ when(mPackageManager.getPackagesHoldingPermissions(
+ new String[] { android.Manifest.permission.MANAGE_USB },
+ PackageManager.MATCH_SYSTEM_ONLY))
+ .thenReturn(List.of(mPackageInfo));
+
+ when(mRestrictUsbOverlayActivitiesProperty.getBoolean()).thenReturn(true);
+ when(mPackageManager.getProperty(
+ eq(PROPERTY_RESTRICT_USB_OVERLAY_ACTIVITIES), eq(TEST_PACKAGE_NAME)))
+ .thenReturn(mRestrictUsbOverlayActivitiesProperty);
}
@After
@@ -130,66 +172,59 @@
}
@Test
- public void testDeviceAttached_flagTrueWithoutForegroundActivity_resolveActivityCalled() {
- when(Flags.allowRestrictionOfOverlayActivities()).thenReturn(true);
+ public void testDeviceAttached_foregroundActivityWithManifestField_resolveActivityNotCalled() {
+ mUsbProfileGroupSettingsManager.deviceAttached(mUsbDevice);
+
+ verify(mUsbUserSettingsManager, times(0)).queryIntentActivities(any(Intent.class));
+ }
+
+ @Test
+ public void testDeviceAttached_noForegroundActivity_resolveActivityCalled() {
when(mActivityManager.getRunningAppProcesses()).thenReturn(new ArrayList<>());
- when(mPackageManager.getPackagesHoldingPermissions(
- new String[]{android.Manifest.permission.MANAGE_USB},
- PackageManager.MATCH_SYSTEM_ONLY)).thenReturn(List.of(mPackageInfo));
- UsbDevice device = Mockito.mock(UsbDevice.class);
- mUsbProfileGroupSettingsManager.deviceAttached(device);
+
+ mUsbProfileGroupSettingsManager.deviceAttached(mUsbDevice);
+
verify(mUsbUserSettingsManager).queryIntentActivities(any(Intent.class));
}
@Test
public void testDeviceAttached_noForegroundActivityWithUsbPermission_resolveActivityCalled() {
- when(Flags.allowRestrictionOfOverlayActivities()).thenReturn(true);
- when(mActivityManager.getRunningAppProcesses()).thenReturn(List.of(mRunningAppProcessInfo));
when(mPackageManager.getPackagesHoldingPermissions(
- new String[]{android.Manifest.permission.MANAGE_USB},
- PackageManager.MATCH_SYSTEM_ONLY)).thenReturn(new ArrayList<>());
- UsbDevice device = Mockito.mock(UsbDevice.class);
- mUsbProfileGroupSettingsManager.deviceAttached(device);
+ new String[] { android.Manifest.permission.MANAGE_USB },
+ PackageManager.MATCH_SYSTEM_ONLY))
+ .thenReturn(new ArrayList<>());
+
+ mUsbProfileGroupSettingsManager.deviceAttached(mUsbDevice);
+
verify(mUsbUserSettingsManager).queryIntentActivities(any(Intent.class));
}
@Test
- public void testDeviceAttached_foregroundActivityWithManifestField_resolveActivityNotCalled() {
- when(Flags.allowRestrictionOfOverlayActivities()).thenReturn(true);
- when(mProperty.getBoolean()).thenReturn(true);
- when(mActivityManager.getRunningAppProcesses()).thenReturn(List.of(mRunningAppProcessInfo));
- when(mPackageManager.getPackagesHoldingPermissions(
- new String[]{android.Manifest.permission.MANAGE_USB},
- PackageManager.MATCH_SYSTEM_ONLY)).thenReturn(List.of(mPackageInfo));
- UsbDevice device = Mockito.mock(UsbDevice.class);
- mUsbProfileGroupSettingsManager.deviceAttached(device);
- verify(mUsbUserSettingsManager, times(0))
- .queryIntentActivities(any(Intent.class));
- }
+ public void testDeviceAttached_restricUsbOverlayPropertyDisabled_resolveActivityCalled() {
+ when(mRestrictUsbOverlayActivitiesProperty.getBoolean()).thenReturn(false);
- @Test
- public void testDeviceAttached_foregroundActivityWithoutManifestField_resolveActivityCalled() {
- when(Flags.allowRestrictionOfOverlayActivities()).thenReturn(true);
- when(mProperty.getBoolean()).thenReturn(false);
- when(mActivityManager.getRunningAppProcesses()).thenReturn(List.of(mRunningAppProcessInfo));
- when(mPackageManager.getPackagesHoldingPermissions(
- new String[]{android.Manifest.permission.MANAGE_USB},
- PackageManager.MATCH_SYSTEM_ONLY)).thenReturn(List.of(mPackageInfo));
- UsbDevice device = Mockito.mock(UsbDevice.class);
- mUsbProfileGroupSettingsManager.deviceAttached(device);
+ mUsbProfileGroupSettingsManager.deviceAttached(mUsbDevice);
+
verify(mUsbUserSettingsManager).queryIntentActivities(any(Intent.class));
}
@Test
- public void testDeviceAttached_flagFalseForegroundActivity_resolveActivityCalled() {
+ public void testDeviceAttached_flagFalse_resolveActivityCalled() {
when(Flags.allowRestrictionOfOverlayActivities()).thenReturn(false);
- when(mProperty.getBoolean()).thenReturn(true);
- when(mActivityManager.getRunningAppProcesses()).thenReturn(List.of(mRunningAppProcessInfo));
- when(mPackageManager.getPackagesHoldingPermissions(
- new String[]{android.Manifest.permission.MANAGE_USB},
- PackageManager.MATCH_SYSTEM_ONLY)).thenReturn(List.of(mPackageInfo));
- UsbDevice device = Mockito.mock(UsbDevice.class);
- mUsbProfileGroupSettingsManager.deviceAttached(device);
+
+ mUsbProfileGroupSettingsManager.deviceAttached(mUsbDevice);
+
verify(mUsbUserSettingsManager).queryIntentActivities(any(Intent.class));
}
+
+ @Test
+ public void
+ testDeviceAttached_setupNotCompleteAndNoBlockingActivities_resolveActivityNotCalled() {
+ when(mRestrictUsbOverlayActivitiesProperty.getBoolean()).thenReturn(false);
+ Settings.Secure.putInt(mContentResolver, USER_SETUP_COMPLETE, 0);
+
+ mUsbProfileGroupSettingsManager.deviceAttached(mUsbDevice);
+
+ verify(mUsbUserSettingsManager, times(0)).queryIntentActivities(any(Intent.class));
+ }
}
diff --git a/tests/inputmethod/ConcurrentMultiSessionImeTest/Android.bp b/tests/inputmethod/ConcurrentMultiSessionImeTest/Android.bp
index 0e0d212..4c531b8 100644
--- a/tests/inputmethod/ConcurrentMultiSessionImeTest/Android.bp
+++ b/tests/inputmethod/ConcurrentMultiSessionImeTest/Android.bp
@@ -20,9 +20,12 @@
android_test {
name: "ConcurrentMultiSessionImeTest",
srcs: ["src/**/*.java"],
+ resource_dirs: ["res"],
libs: ["android.test.runner"],
static_libs: [
"androidx.test.ext.junit",
+ "androidx.test.rules",
+ "compatibility-device-util-axt",
"platform-test-annotations",
"platform-test-rules",
"truth",
@@ -35,7 +38,11 @@
test_suites: [
"general-tests",
],
- sdk_version: "current",
+ sdk_version: "test_current",
+
+ data: [
+ ":CtsMockInputMethod",
+ ],
// Store test artifacts in separated directories for easier debugging.
per_testcase_directory: true,
diff --git a/tests/inputmethod/ConcurrentMultiSessionImeTest/AndroidManifest.xml b/tests/inputmethod/ConcurrentMultiSessionImeTest/AndroidManifest.xml
index 0defe5b..2e336ca 100644
--- a/tests/inputmethod/ConcurrentMultiSessionImeTest/AndroidManifest.xml
+++ b/tests/inputmethod/ConcurrentMultiSessionImeTest/AndroidManifest.xml
@@ -17,6 +17,17 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.server.inputmethod.multisessiontest">
+ <application>
+ <uses-library android:name="android.test.runner" />
+ <activity android:name=".MainActivity"
+ android:theme="@android:style/Theme.Material.NoActionBar"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ </intent-filter>
+ </activity>
+ </application>
+
<instrumentation
android:name="androidx.test.runner.AndroidJUnitRunner"
android:targetPackage="com.android.server.inputmethod.multisessiontest"></instrumentation>
diff --git a/tests/inputmethod/ConcurrentMultiSessionImeTest/AndroidTest.xml b/tests/inputmethod/ConcurrentMultiSessionImeTest/AndroidTest.xml
index fd598c5..d5ed203 100644
--- a/tests/inputmethod/ConcurrentMultiSessionImeTest/AndroidTest.xml
+++ b/tests/inputmethod/ConcurrentMultiSessionImeTest/AndroidTest.xml
@@ -17,13 +17,28 @@
<configuration description="Config for Concurrent Multi-Session IME tests">
<object class="com.android.tradefed.testtype.suite.module.DeviceFeatureModuleController"
type="module_controller">
- <option name="required-feature" value="android.software.input_methods" />
+ <!-- TODO(b/323372972): require this feature once the bug is fixed. -->
+ <!-- option name="required-feature" value="android.software.input_methods" -->
<!-- Currently enabled to automotive only -->
<option name="required-feature" value="android.hardware.type.automotive" />
</object>
<option name="test-suite-tag" value="apct" />
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="force-install-mode" value="FULL" />
+ <option name="test-file-name" value="ConcurrentMultiSessionImeTest.apk" />
+ <option name="test-file-name" value="CtsMockInputMethod.apk" />
+ </target_preparer>
+
+ <!-- RunOnSecondaryUserTargetPreparer must run after SuiteApkInstaller. -->
+ <target_preparer class="com.android.tradefed.targetprep.RunOnSecondaryUserTargetPreparer">
+ <option name="start-background-user" value="true" />
+ <option name="test-package-name" value="com.android.server.inputmethod.multisessiontest" />
+ <option name="test-package-name" value="com.android.cts.mockime" />
+ </target_preparer>
+
<target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
<option name="run-command" value="setprop debug.wm.disable_deprecated_abi_dialog 1" />
<option name="run-command" value="settings put secure show_ime_with_hard_keyboard 1" />
@@ -31,12 +46,6 @@
value="settings delete secure show_ime_with_hard_keyboard" />
</target_preparer>
- <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
- <option name="cleanup-apks" value="true" />
- <option name="force-install-mode" value="FULL" />
- <option name="test-file-name" value="ConcurrentMultiSessionImeTest.apk" />
- </target_preparer>
-
<test class="com.android.tradefed.testtype.AndroidJUnitTest">
<option name="package" value="com.android.server.inputmethod.multisessiontest" />
</test>
diff --git a/tests/inputmethod/ConcurrentMultiSessionImeTest/res/layout/main_activity.xml b/tests/inputmethod/ConcurrentMultiSessionImeTest/res/layout/main_activity.xml
new file mode 100644
index 0000000..e16d286
--- /dev/null
+++ b/tests/inputmethod/ConcurrentMultiSessionImeTest/res/layout/main_activity.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2024 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:fitsSystemWindows="true">
+ <EditText
+ android:id="@+id/edit_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:hint="Input text here"/>
+</FrameLayout>
diff --git a/tests/inputmethod/ConcurrentMultiSessionImeTest/src/com/android/server/inputmethod/multisessiontest/ConcurrentMultiUserTest.java b/tests/inputmethod/ConcurrentMultiSessionImeTest/src/com/android/server/inputmethod/multisessiontest/ConcurrentMultiUserTest.java
index a5ce69d..56dbde0 100644
--- a/tests/inputmethod/ConcurrentMultiSessionImeTest/src/com/android/server/inputmethod/multisessiontest/ConcurrentMultiUserTest.java
+++ b/tests/inputmethod/ConcurrentMultiSessionImeTest/src/com/android/server/inputmethod/multisessiontest/ConcurrentMultiUserTest.java
@@ -16,16 +16,27 @@
package com.android.server.inputmethod.multisessiontest;
-import static com.google.common.truth.Truth.assertThat;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
-import android.content.Context;
-import android.content.pm.PackageManager;
+import static com.android.compatibility.common.util.concurrentuser.ConcurrentUserActivityUtils.getResponderUserId;
+import static com.android.compatibility.common.util.concurrentuser.ConcurrentUserActivityUtils.launchActivityAsUserSync;
+import static com.android.compatibility.common.util.concurrentuser.ConcurrentUserActivityUtils.sendBundleAndWaitForReply;
+import static com.android.server.inputmethod.multisessiontest.TestRequestConstants.KEY_REQUEST_CODE;
+import static com.android.server.inputmethod.multisessiontest.TestRequestConstants.KEY_RESULT_CODE;
+import static com.android.server.inputmethod.multisessiontest.TestRequestConstants.REPLY_IME_HIDDEN;
+import static com.android.server.inputmethod.multisessiontest.TestRequestConstants.REQUEST_IME_STATUS;
-import androidx.test.platform.app.InstrumentationRegistry;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import android.content.ComponentName;
+import android.os.Bundle;
+
+import androidx.test.core.app.ActivityScenario;
import com.android.bedstead.harrier.BedsteadJUnit4;
import com.android.bedstead.harrier.DeviceState;
+import org.junit.After;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Rule;
@@ -39,19 +50,56 @@
@Rule
public static final DeviceState sDeviceState = new DeviceState();
+ private static final ComponentName TEST_ACTIVITY = new ComponentName(
+ getInstrumentation().getTargetContext().getPackageName(),
+ MainActivity.class.getName());
+
+ private ActivityScenario<MainActivity> mActivityScenario;
+ private MainActivity mActivity;
+ private int mPeerUserId;
+
@Before
- public void doBeforeEachTest() {
- // No op
+ public void setUp() {
+ // Launch passenger activity.
+ mPeerUserId = getResponderUserId();
+ launchActivityAsUserSync(TEST_ACTIVITY, mPeerUserId);
+
+ // Launch driver activity.
+ mActivityScenario = ActivityScenario.launch(MainActivity.class);
+ mActivityScenario.onActivity(activity -> mActivity = activity);
+ }
+
+ @After
+ public void tearDown() {
+ if (mActivityScenario != null) {
+ mActivityScenario.close();
+ }
}
@Test
- public void behaviorBeingTested_expectedResult() {
- // Sample test
- Context context =
- InstrumentationRegistry.getInstrumentation().getTargetContext();
- assertThat(context.getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_AUTOMOTIVE)).isTrue();
- assertThat(context.getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_INPUT_METHODS)).isTrue();
+ public void driverShowImeNotAffectPassenger() {
+ assertDriverImeHidden();
+ assertPassengerImeHidden();
+
+ showDriverImeAndAssert();
+ assertPassengerImeHidden();
+ }
+
+ private void assertDriverImeHidden() {
+ assertWithMessage("Driver IME should be hidden")
+ .that(mActivity.isMyImeVisible()).isFalse();
+ }
+
+ private void assertPassengerImeHidden() {
+ final Bundle bundleToSend = new Bundle();
+ bundleToSend.putInt(KEY_REQUEST_CODE, REQUEST_IME_STATUS);
+ Bundle receivedBundle = sendBundleAndWaitForReply(TEST_ACTIVITY.getPackageName(),
+ mPeerUserId, bundleToSend);
+ assertWithMessage("Passenger IME should be hidden")
+ .that(receivedBundle.getInt(KEY_RESULT_CODE)).isEqualTo(REPLY_IME_HIDDEN);
+ }
+
+ private void showDriverImeAndAssert() {
+ mActivity.showMyImeAndWait();
}
}
diff --git a/tests/inputmethod/ConcurrentMultiSessionImeTest/src/com/android/server/inputmethod/multisessiontest/MainActivity.java b/tests/inputmethod/ConcurrentMultiSessionImeTest/src/com/android/server/inputmethod/multisessiontest/MainActivity.java
new file mode 100644
index 0000000..e3f84c1
--- /dev/null
+++ b/tests/inputmethod/ConcurrentMultiSessionImeTest/src/com/android/server/inputmethod/multisessiontest/MainActivity.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.inputmethod.multisessiontest;
+
+import static com.android.server.inputmethod.multisessiontest.TestRequestConstants.KEY_REQUEST_CODE;
+import static com.android.server.inputmethod.multisessiontest.TestRequestConstants.KEY_RESULT_CODE;
+import static com.android.server.inputmethod.multisessiontest.TestRequestConstants.REPLY_IME_HIDDEN;
+import static com.android.server.inputmethod.multisessiontest.TestRequestConstants.REPLY_IME_SHOWN;
+import static com.android.server.inputmethod.multisessiontest.TestRequestConstants.REQUEST_IME_STATUS;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.EditText;
+
+import androidx.core.view.ViewCompat;
+import androidx.core.view.WindowInsetsCompat;
+
+import com.android.compatibility.common.util.PollingCheck;
+import com.android.compatibility.common.util.concurrentuser.ConcurrentUserActivityBase;
+
+/**
+ * An {@link Activity} to test multiple concurrent session IME.
+ */
+public final class MainActivity extends ConcurrentUserActivityBase {
+ private static final String TAG = ConcurrentMultiUserTest.class.getSimpleName();
+ private static final long WAIT_IME_TIMEOUT_MS = 3000;
+
+ private EditText mEditor;
+ private InputMethodManager mImm;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ Log.v(TAG, "Create MainActivity as user " + getUserId() + " on display "
+ + getDisplayId());
+ setContentView(R.layout.main_activity);
+ mImm = getSystemService(InputMethodManager.class);
+ mEditor = requireViewById(R.id.edit_text);
+ }
+
+ @Override
+ protected Bundle onBundleReceived(Bundle receivedBundle) {
+ final int requestCode = receivedBundle.getInt(KEY_REQUEST_CODE);
+ Log.v(TAG, "onBundleReceived() with request code:" + requestCode);
+ final Bundle replyBundle = new Bundle();
+ switch (requestCode) {
+ case REQUEST_IME_STATUS:
+ replyBundle.putInt(KEY_RESULT_CODE,
+ isMyImeVisible() ? REPLY_IME_SHOWN : REPLY_IME_HIDDEN);
+ break;
+ default:
+ throw new RuntimeException("Received undefined request code:" + requestCode);
+ }
+ return replyBundle;
+ }
+
+ boolean isMyImeVisible() {
+ final WindowInsetsCompat insets = ViewCompat.getRootWindowInsets(mEditor);
+ return insets == null ? false : insets.isVisible(WindowInsetsCompat.Type.ime());
+ }
+
+ void showMyImeAndWait() {
+ Log.v(TAG, "showSoftInput");
+ runOnUiThread(() -> {
+ // requestFocus() must run on UI thread.
+ if (!mEditor.requestFocus()) {
+ Log.e(TAG, "Failed to focus on mEditor");
+ return;
+ }
+ if (!mImm.showSoftInput(mEditor, /* flags= */ 0)) {
+ Log.e(TAG, String.format("Failed to show my IME as user %d, "
+ + "mEditor:focused=%b,hasWindowFocus=%b", getUserId(),
+ mEditor.isFocused(), mEditor.hasWindowFocus()));
+ }
+ });
+ PollingCheck.waitFor(WAIT_IME_TIMEOUT_MS, () -> isMyImeVisible(),
+ String.format("My IME (user %d) didn't show up", getUserId()));
+ }
+}
diff --git a/tests/inputmethod/ConcurrentMultiSessionImeTest/src/com/android/server/inputmethod/multisessiontest/TestRequestConstants.java b/tests/inputmethod/ConcurrentMultiSessionImeTest/src/com/android/server/inputmethod/multisessiontest/TestRequestConstants.java
new file mode 100644
index 0000000..1501bfb
--- /dev/null
+++ b/tests/inputmethod/ConcurrentMultiSessionImeTest/src/com/android/server/inputmethod/multisessiontest/TestRequestConstants.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.inputmethod.multisessiontest;
+
+final class TestRequestConstants {
+ private TestRequestConstants() {
+ }
+
+ public static final String KEY_REQUEST_CODE = "key_request_code";
+ public static final String KEY_RESULT_CODE = "key_result_code";
+
+ public static final int REQUEST_IME_STATUS = 1;
+ public static final int REPLY_IME_SHOWN = 2;
+ public static final int REPLY_IME_HIDDEN = 3;
+}
diff --git a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
index 960b57c..580efe1 100644
--- a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
+++ b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
@@ -70,6 +70,7 @@
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.net.Uri;
+import android.net.vcn.Flags;
import android.net.vcn.IVcnStatusCallback;
import android.net.vcn.IVcnUnderlyingNetworkPolicyListener;
import android.net.vcn.VcnConfig;
@@ -82,7 +83,9 @@
import android.os.PersistableBundle;
import android.os.Process;
import android.os.UserHandle;
+import android.os.UserManager;
import android.os.test.TestLooper;
+import android.platform.test.flag.junit.SetFlagsRule;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
@@ -101,6 +104,7 @@
import com.android.server.vcn.util.PersistableBundleUtils.PersistableBundleWrapper;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
@@ -118,6 +122,8 @@
@RunWith(AndroidJUnit4.class)
@SmallTest
public class VcnManagementServiceTest {
+ @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
private static final String CONTEXT_ATTRIBUTION_TAG = "VCN";
private static final String TEST_PACKAGE_NAME =
VcnManagementServiceTest.class.getPackage().getName();
@@ -129,7 +135,12 @@
private static final ParcelUuid TEST_UUID_3 = new ParcelUuid(new UUID(2, 2));
private static final VcnConfig TEST_VCN_CONFIG;
private static final VcnConfig TEST_VCN_CONFIG_PKG_2;
- private static final int TEST_UID = Process.FIRST_APPLICATION_UID;
+
+ private static final int TEST_UID = 1010000; // A non-system user
+ private static final UserHandle TEST_USER_HANDLE = UserHandle.getUserHandleForUid(TEST_UID);
+ private static final UserHandle TEST_USER_HANDLE_OTHER =
+ UserHandle.of(TEST_USER_HANDLE.getIdentifier() + 1);
+
private static final String TEST_IFACE_NAME = "TEST_IFACE";
private static final String TEST_IFACE_NAME_2 = "TEST_IFACE2";
private static final LinkProperties TEST_LP_1 = new LinkProperties();
@@ -187,6 +198,7 @@
private final TelephonyManager mTelMgr = mock(TelephonyManager.class);
private final SubscriptionManager mSubMgr = mock(SubscriptionManager.class);
private final AppOpsManager mAppOpsMgr = mock(AppOpsManager.class);
+ private final UserManager mUserManager = mock(UserManager.class);
private final VcnContext mVcnContext = mock(VcnContext.class);
private final PersistableBundleUtils.LockingReadWriteHelper mConfigReadWriteHelper =
mock(PersistableBundleUtils.LockingReadWriteHelper.class);
@@ -218,6 +230,9 @@
Context.TELEPHONY_SUBSCRIPTION_SERVICE,
SubscriptionManager.class);
setupSystemService(mMockContext, mAppOpsMgr, Context.APP_OPS_SERVICE, AppOpsManager.class);
+ setupSystemService(mMockContext, mUserManager, Context.USER_SERVICE, UserManager.class);
+
+ doReturn(TEST_USER_HANDLE).when(mUserManager).getMainUser();
doReturn(TEST_PACKAGE_NAME).when(mMockContext).getOpPackageName();
@@ -267,6 +282,8 @@
@Before
public void setUp() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_ENFORCE_MAIN_USER);
+
doNothing()
.when(mMockContext)
.enforceCallingOrSelfPermission(
@@ -717,10 +734,8 @@
}
@Test
- public void testSetVcnConfigRequiresSystemUser() throws Exception {
- doReturn(UserHandle.getUid(UserHandle.MIN_SECONDARY_USER_ID, TEST_UID))
- .when(mMockDeps)
- .getBinderCallingUid();
+ public void testSetVcnConfigRequiresMainUser() throws Exception {
+ doReturn(TEST_USER_HANDLE_OTHER).when(mUserManager).getMainUser();
try {
mVcnMgmtSvc.setVcnConfig(TEST_UUID_1, TEST_VCN_CONFIG, TEST_PACKAGE_NAME);
@@ -832,10 +847,8 @@
}
@Test
- public void testClearVcnConfigRequiresSystemUser() throws Exception {
- doReturn(UserHandle.getUid(UserHandle.MIN_SECONDARY_USER_ID, TEST_UID))
- .when(mMockDeps)
- .getBinderCallingUid();
+ public void testClearVcnConfigRequiresMainUser() throws Exception {
+ doReturn(TEST_USER_HANDLE_OTHER).when(mUserManager).getMainUser();
try {
mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1, TEST_PACKAGE_NAME);
@@ -921,10 +934,8 @@
}
@Test
- public void testGetConfiguredSubscriptionGroupsRequiresSystemUser() throws Exception {
- doReturn(UserHandle.getUid(UserHandle.MIN_SECONDARY_USER_ID, TEST_UID))
- .when(mMockDeps)
- .getBinderCallingUid();
+ public void testGetConfiguredSubscriptionGroupsRequiresMainUser() throws Exception {
+ doReturn(TEST_USER_HANDLE_OTHER).when(mUserManager).getMainUser();
try {
mVcnMgmtSvc.getConfiguredSubscriptionGroups(TEST_PACKAGE_NAME);
diff --git a/tests/vcn/java/com/android/server/vcn/routeselection/IpSecPacketLossDetectorTest.java b/tests/vcn/java/com/android/server/vcn/routeselection/IpSecPacketLossDetectorTest.java
index c8b60e5..441a4ae 100644
--- a/tests/vcn/java/com/android/server/vcn/routeselection/IpSecPacketLossDetectorTest.java
+++ b/tests/vcn/java/com/android/server/vcn/routeselection/IpSecPacketLossDetectorTest.java
@@ -20,6 +20,7 @@
import static android.net.vcn.VcnManager.VCN_NETWORK_SELECTION_MAX_SEQ_NUM_INCREASE_PER_SECOND_KEY;
import static android.net.vcn.VcnManager.VCN_NETWORK_SELECTION_POLL_IPSEC_STATE_INTERVAL_SECONDS_KEY;
+import static com.android.server.vcn.routeselection.IpSecPacketLossDetector.IPSEC_PACKET_LOSS_PERCENT_THRESHOLD_DISABLE_DETECTOR;
import static com.android.server.vcn.routeselection.IpSecPacketLossDetector.MIN_VALID_EXPECTED_RX_PACKET_NUM;
import static com.android.server.vcn.routeselection.IpSecPacketLossDetector.getMaxSeqNumIncreasePerSecond;
import static com.android.server.vcn.util.PersistableBundleUtils.PersistableBundleWrapper;
@@ -584,4 +585,56 @@
MAX_SEQ_NUM_INCREASE_DEFAULT_DISABLED,
getMaxSeqNumIncreasePerSecond(mCarrierConfig));
}
+
+ private IpSecPacketLossDetector newDetectorAndSetTransform(int threshold) throws Exception {
+ when(mCarrierConfig.getInt(
+ eq(VCN_NETWORK_SELECTION_IPSEC_PACKET_LOSS_PERCENT_THRESHOLD_KEY),
+ anyInt()))
+ .thenReturn(threshold);
+
+ final IpSecPacketLossDetector detector =
+ new IpSecPacketLossDetector(
+ mVcnContext,
+ mNetwork,
+ mCarrierConfig,
+ mMetricMonitorCallback,
+ mDependencies);
+
+ detector.setIsSelectedUnderlyingNetwork(true /* setIsSelected */);
+ detector.setInboundTransformInternal(mIpSecTransform);
+
+ return detector;
+ }
+
+ @Test
+ public void testDisableAndEnableDetectorWithCarrierConfig() throws Exception {
+ final IpSecPacketLossDetector detector =
+ newDetectorAndSetTransform(IPSEC_PACKET_LOSS_PERCENT_THRESHOLD_DISABLE_DETECTOR);
+
+ assertFalse(detector.isStarted());
+
+ when(mCarrierConfig.getInt(
+ eq(VCN_NETWORK_SELECTION_IPSEC_PACKET_LOSS_PERCENT_THRESHOLD_KEY),
+ anyInt()))
+ .thenReturn(IPSEC_PACKET_LOSS_PERCENT_THRESHOLD);
+ detector.setCarrierConfig(mCarrierConfig);
+
+ assertTrue(detector.isStarted());
+ }
+
+ @Test
+ public void testEnableAndDisableDetectorWithCarrierConfig() throws Exception {
+ final IpSecPacketLossDetector detector =
+ newDetectorAndSetTransform(IPSEC_PACKET_LOSS_PERCENT_THRESHOLD);
+
+ assertTrue(detector.isStarted());
+
+ when(mCarrierConfig.getInt(
+ eq(VCN_NETWORK_SELECTION_IPSEC_PACKET_LOSS_PERCENT_THRESHOLD_KEY),
+ anyInt()))
+ .thenReturn(IPSEC_PACKET_LOSS_PERCENT_THRESHOLD_DISABLE_DETECTOR);
+ detector.setCarrierConfig(mCarrierConfig);
+
+ assertFalse(detector.isStarted());
+ }
}
diff --git a/tests/vcn/java/com/android/server/vcn/routeselection/NetworkEvaluationTestBase.java b/tests/vcn/java/com/android/server/vcn/routeselection/NetworkEvaluationTestBase.java
index edad678..0439d5f5 100644
--- a/tests/vcn/java/com/android/server/vcn/routeselection/NetworkEvaluationTestBase.java
+++ b/tests/vcn/java/com/android/server/vcn/routeselection/NetworkEvaluationTestBase.java
@@ -123,6 +123,7 @@
mSetFlagsRule.enableFlags(Flags.FLAG_VALIDATE_NETWORK_ON_IPSEC_LOSS);
mSetFlagsRule.enableFlags(Flags.FLAG_EVALUATE_IPSEC_LOSS_ON_LP_NC_CHANGE);
mSetFlagsRule.enableFlags(Flags.FLAG_HANDLE_SEQ_NUM_LEAP);
+ mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_DISABLE_IPSEC_LOSS_DETECTOR);
when(mNetwork.getNetId()).thenReturn(-1);
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
index f1e4ead..669cddb 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -443,7 +443,7 @@
manifest_action.Action(AutoGenerateIsSplitRequired);
manifest_action.Action(VerifyManifest);
manifest_action.Action(FixCoreAppAttribute);
- manifest_action.Action([&](xml::Element* el) -> bool {
+ manifest_action.Action([this, diag](xml::Element* el) -> bool {
EnsureNamespaceIsDeclared("android", xml::kSchemaAndroid, &el->namespace_decls);
if (options_.version_name_default) {
@@ -506,7 +506,7 @@
manifest_action["eat-comment"];
// Uses-sdk actions.
- manifest_action["uses-sdk"].Action([&](xml::Element* el) -> bool {
+ manifest_action["uses-sdk"].Action([this](xml::Element* el) -> bool {
if (options_.min_sdk_version_default &&
el->FindAttribute(xml::kSchemaAndroid, "minSdkVersion") == nullptr) {
// There was no minSdkVersion defined and we have a default to assign.
@@ -528,7 +528,7 @@
// Instrumentation actions.
manifest_action["instrumentation"].Action(RequiredNameIsJavaClassName);
- manifest_action["instrumentation"].Action([&](xml::Element* el) -> bool {
+ manifest_action["instrumentation"].Action([this](xml::Element* el) -> bool {
if (!options_.rename_instrumentation_target_package) {
return true;
}
@@ -544,7 +544,7 @@
manifest_action["attribution"];
manifest_action["attribution"]["inherit-from"];
manifest_action["original-package"];
- manifest_action["overlay"].Action([&](xml::Element* el) -> bool {
+ manifest_action["overlay"].Action([this](xml::Element* el) -> bool {
if (options_.rename_overlay_target_package) {
if (xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "targetPackage")) {
attr->value = options_.rename_overlay_target_package.value();
@@ -625,7 +625,7 @@
uses_package_action["additional-certificate"];
if (options_.debug_mode) {
- application_action.Action([&](xml::Element* el) -> bool {
+ application_action.Action([](xml::Element* el) -> bool {
xml::Attribute *attr = el->FindOrCreateAttribute(xml::kSchemaAndroid, "debuggable");
attr->value = "true";
return true;
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/InMemoryOutputFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/InMemoryOutputFilter.kt
index 5659a35..2e144f5 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/InMemoryOutputFilter.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/InMemoryOutputFilter.kt
@@ -15,11 +15,11 @@
*/
package com.android.hoststubgen.filters
-import com.android.hoststubgen.UnknownApiException
import com.android.hoststubgen.addNonNullElement
import com.android.hoststubgen.asm.ClassNodes
import com.android.hoststubgen.asm.toHumanReadableClassName
import com.android.hoststubgen.asm.toHumanReadableMethodName
+import com.android.hoststubgen.log
// TODO: Validate all input names.
@@ -48,30 +48,30 @@
return mPolicies[getClassKey(className)] ?: super.getPolicyForClass(className)
}
- private fun ensureClassExists(className: String) {
+ private fun checkClass(className: String) {
if (classes.findClass(className) == null) {
- throw UnknownApiException("Unknown class $className")
+ log.w("Unknown class $className")
}
}
- private fun ensureFieldExists(className: String, fieldName: String) {
+ private fun checkField(className: String, fieldName: String) {
if (classes.findField(className, fieldName) == null) {
- throw UnknownApiException("Unknown field $className.$fieldName")
+ log.w("Unknown field $className.$fieldName")
}
}
- private fun ensureMethodExists(
+ private fun checkMethod(
className: String,
methodName: String,
descriptor: String
) {
if (classes.findMethod(className, methodName, descriptor) == null) {
- throw UnknownApiException("Unknown method $className.$methodName$descriptor")
+ log.w("Unknown method $className.$methodName$descriptor")
}
}
fun setPolicyForClass(className: String, policy: FilterPolicyWithReason) {
- ensureClassExists(className)
+ checkClass(className)
mPolicies[getClassKey(className)] = policy
}
@@ -81,7 +81,7 @@
}
fun setPolicyForField(className: String, fieldName: String, policy: FilterPolicyWithReason) {
- ensureFieldExists(className, fieldName)
+ checkField(className, fieldName)
mPolicies[getFieldKey(className, fieldName)] = policy
}
@@ -100,7 +100,7 @@
descriptor: String,
policy: FilterPolicyWithReason,
) {
- ensureMethodExists(className, methodName, descriptor)
+ checkMethod(className, methodName, descriptor)
mPolicies[getMethodKey(className, methodName, descriptor)] = policy
}
@@ -110,8 +110,8 @@
}
fun setRenameTo(className: String, methodName: String, descriptor: String, toName: String) {
- ensureMethodExists(className, methodName, descriptor)
- ensureMethodExists(className, toName, descriptor)
+ checkMethod(className, methodName, descriptor)
+ checkMethod(className, toName, descriptor)
mRenames[getMethodKey(className, methodName, descriptor)] = toName
}
@@ -121,7 +121,7 @@
}
fun setNativeSubstitutionClass(from: String, to: String) {
- ensureClassExists(from)
+ checkClass(from)
// Native substitute classes may be provided from other jars, so we can't do this check.
// ensureClassExists(to)