Merge "Revert "Call minikin::getBounds instead of using Layout.""
diff --git a/Android.bp b/Android.bp
index ae717f1..afdd832 100644
--- a/Android.bp
+++ b/Android.bp
@@ -374,7 +374,7 @@
java_library {
name: "framework-updatable-stubs-module_libs_api",
static_libs: [
- "framework-appsearch-stubs", // TODO: Update to module_libs_api when there is one.
+ "framework-appsearch.stubs.module_lib",
"framework-graphics.stubs.module_lib",
"framework-media.stubs.module_lib",
"framework-mediaprovider.stubs.module_lib",
@@ -393,7 +393,7 @@
installable: false,
static_libs: [
"framework-minus-apex",
- "framework-appsearch",
+ "framework-appsearch.impl",
"framework-graphics.impl",
"framework-mediaprovider.impl",
"framework-permission.impl",
@@ -624,8 +624,7 @@
static_libs: [
"app-compat-annotations",
"framework-minus-apex",
- // TODO(b/146218515): should be removed
- "framework-appsearch",
+ "framework-appsearch.impl", // TODO(b/146218515): should be removed
"framework-updatable-stubs-module_libs_api",
],
sdk_version: "core_platform",
@@ -797,7 +796,6 @@
name: "framework-services-net-module-wifi-shared-srcs",
srcs: [
"core/java/android/net/DhcpResults.java",
- "core/java/android/net/util/IpUtils.java",
"core/java/android/util/LocalLog.java",
],
}
diff --git a/StubLibraries.bp b/StubLibraries.bp
index be24bd7..4aab65e 100644
--- a/StubLibraries.bp
+++ b/StubLibraries.bp
@@ -142,11 +142,6 @@
baseline_file: "api/lint-baseline.txt",
},
},
- dist: {
- targets: ["sdk", "win_sdk"],
- dir: "apistubs/android/public/api",
- dest: "android.txt",
- },
jdiff_enabled: true,
}
@@ -209,11 +204,6 @@
baseline_file: "api/system-lint-baseline.txt",
},
},
- dist: {
- targets: ["sdk", "win_sdk"],
- dir: "apistubs/android/system/api",
- dest: "android.txt",
- },
jdiff_enabled: true,
}
@@ -294,11 +284,6 @@
baseline_file: "api/module-lib-lint-baseline.txt",
},
},
- dist: {
- targets: ["sdk", "win_sdk"],
- dir: "apistubs/android/module-lib/api",
- dest: "android.txt",
- },
}
droidstubs {
@@ -367,6 +352,7 @@
srcs: [ ":api-stubs-docs-non-updatable" ],
static_libs: [
"conscrypt.module.public.api.stubs",
+ "framework-appsearch.stubs",
"framework-graphics.stubs",
"framework-media.stubs",
"framework-mediaprovider.stubs",
@@ -412,7 +398,7 @@
srcs: [ ":system-api-stubs-docs-non-updatable" ],
static_libs: [
"conscrypt.module.public.api.stubs",
- "framework-appsearch-stubs", // TODO: standardize appsearch stubs
+ "framework-appsearch.stubs.system",
"framework-graphics.stubs.system",
"framework-media.stubs.system",
"framework-mediaprovider.stubs.system",
diff --git a/apex/appsearch/framework/Android.bp b/apex/appsearch/framework/Android.bp
index 321f471..e10fb07 100644
--- a/apex/appsearch/framework/Android.bp
+++ b/apex/appsearch/framework/Android.bp
@@ -21,60 +21,17 @@
path: "java",
}
-java_library {
+java_sdk_library {
name: "framework-appsearch",
- installable: true,
+ srcs: [ ":framework-appsearch-sources" ],
sdk_version: "core_platform", // TODO(b/146218515) should be module_current
- srcs: [":framework-appsearch-sources"],
- hostdex: true, // for hiddenapi check
- libs: [
- "framework-minus-apex", // TODO(b/146218515) should be removed
- ],
+ impl_only_libs: ["framework-minus-apex"], // TODO(b/146218515) should be removed
static_libs: ["icing-java-proto-lite"],
- visibility: [
- // TODO(b/146218515) remove this when framework is built with the stub of appsearch
- "//frameworks/base",
- "//frameworks/base/apex/appsearch:__subpackages__",
- ],
- jarjar_rules: "jarjar-rules.txt",
+ defaults: ["framework-module-defaults"],
permitted_packages: ["android.app.appsearch"],
+ jarjar_rules: "jarjar-rules.txt",
+ aidl: {
+ include_dirs: ["frameworks/base/core/java"], // TODO(b/146218515) should be removed
+ },
apex_available: ["com.android.appsearch"],
}
-
-metalava_appsearch_docs_args =
- "--hide-package com.android.server " +
- "--error UnhiddenSystemApi " +
- "--hide RequiresPermission " +
- "--hide MissingPermission " +
- "--hide BroadcastBehavior " +
- "--hide HiddenSuperclass " +
- "--hide DeprecationMismatch " +
- "--hide UnavailableSymbol " +
- "--hide SdkConstant " +
- "--hide HiddenTypeParameter " +
- "--hide Todo --hide Typo " +
- "--hide HiddenTypedefConstant " +
- "--show-annotation android.annotation.SystemApi "
-
-droidstubs {
- name: "framework-appsearch-stubs-srcs",
- srcs: [":framework-appsearch-sources"],
- libs: ["framework-annotations-lib"],
- aidl: {
- include_dirs: ["frameworks/base/core/java"],
- },
- args: metalava_appsearch_docs_args,
- sdk_version: "module_current",
-}
-
-java_library {
- name: "framework-appsearch-stubs",
- srcs: [":framework-appsearch-stubs-srcs"],
- aidl: {
- export_include_dirs: [
- "java",
- ],
- },
- sdk_version: "module_current",
- installable: false,
-}
diff --git a/apex/appsearch/framework/api/current.txt b/apex/appsearch/framework/api/current.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/apex/appsearch/framework/api/current.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/apex/appsearch/framework/api/module-lib-current.txt b/apex/appsearch/framework/api/module-lib-current.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/apex/appsearch/framework/api/module-lib-current.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/apex/appsearch/framework/api/module-lib-removed.txt b/apex/appsearch/framework/api/module-lib-removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/apex/appsearch/framework/api/module-lib-removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/apex/appsearch/framework/api/removed.txt b/apex/appsearch/framework/api/removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/apex/appsearch/framework/api/removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/apex/appsearch/framework/api/system-current.txt b/apex/appsearch/framework/api/system-current.txt
new file mode 100644
index 0000000..4a6194e
--- /dev/null
+++ b/apex/appsearch/framework/api/system-current.txt
@@ -0,0 +1,9 @@
+// Signature format: 2.0
+package android.app.appsearch {
+
+ public class AppSearchManagerFrameworkInitializer {
+ method public static void initialize();
+ }
+
+}
+
diff --git a/apex/appsearch/framework/api/system-removed.txt b/apex/appsearch/framework/api/system-removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/apex/appsearch/framework/api/system-removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/api/Android.bp b/api/Android.bp
index f0218b8..388bb68 100644
--- a/api/Android.bp
+++ b/api/Android.bp
@@ -48,6 +48,7 @@
name: "frameworks-base-api-current-merged.txt",
srcs: [
":conscrypt.module.public.api{.public.api.txt}",
+ ":framework-appsearch{.public.api.txt}",
":framework-graphics{.public.api.txt}",
":framework-media{.public.api.txt}",
":framework-mediaprovider{.public.api.txt}",
@@ -61,12 +62,19 @@
out: ["current.txt"],
tools: ["metalava"],
cmd: "$(location metalava) --no-banner --format=v2 $(in) --api $(out)",
+ dist: {
+ targets: ["sdk", "win_sdk"],
+ dir: "apistubs/android/public/api",
+ dest: "android.txt",
+ },
}
genrule {
name: "frameworks-base-api-removed-merged.txt",
srcs: [
":conscrypt.module.public.api{.public.removed-api.txt}",
+ ":framework-appsearch{.public.removed-api.txt}",
+ ":framework-graphics{.public.removed-api.txt}",
":framework-media{.public.removed-api.txt}",
":framework-mediaprovider{.public.removed-api.txt}",
":framework-permission{.public.removed-api.txt}",
@@ -84,6 +92,7 @@
genrule {
name: "frameworks-base-api-system-current-merged.txt",
srcs: [
+ ":framework-appsearch{.system.api.txt}",
":framework-graphics{.system.api.txt}",
":framework-media{.system.api.txt}",
":framework-mediaprovider{.system.api.txt}",
@@ -97,11 +106,18 @@
out: ["system-current.txt"],
tools: ["metalava"],
cmd: "$(location metalava) --no-banner --format=v2 $(in) --api $(out)",
+ dist: {
+ targets: ["sdk", "win_sdk"],
+ dir: "apistubs/android/system/api",
+ dest: "android.txt",
+ },
}
genrule {
name: "frameworks-base-api-system-removed-merged.txt",
srcs: [
+ ":framework-appsearch{.system.removed-api.txt}",
+ ":framework-graphics{.system.removed-api.txt}",
":framework-media{.system.removed-api.txt}",
":framework-mediaprovider{.system.removed-api.txt}",
":framework-permission{.system.removed-api.txt}",
@@ -119,6 +135,7 @@
genrule {
name: "frameworks-base-api-module-lib-current-merged.txt",
srcs: [
+ ":framework-appsearch{.module-lib.api.txt}",
":framework-graphics{.module-lib.api.txt}",
":framework-media{.module-lib.api.txt}",
":framework-mediaprovider{.module-lib.api.txt}",
@@ -132,11 +149,18 @@
out: ["module-lib-current.txt"],
tools: ["metalava"],
cmd: "$(location metalava) --no-banner --format=v2 $(in) --api $(out)",
+ dist: {
+ targets: ["sdk", "win_sdk"],
+ dir: "apistubs/android/module-lib/api",
+ dest: "android.txt",
+ },
}
genrule {
name: "frameworks-base-api-module-lib-removed-merged.txt",
srcs: [
+ ":framework-appsearch{.module-lib.removed-api.txt}",
+ ":framework-graphics{.module-lib.removed-api.txt}",
":framework-media{.module-lib.removed-api.txt}",
":framework-mediaprovider{.module-lib.removed-api.txt}",
":framework-permission{.module-lib.removed-api.txt}",
diff --git a/api/current.txt b/api/current.txt
index 83df1d9..fc1a265 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -26408,7 +26408,7 @@
method public boolean containsKey(String);
method public int describeContents();
method public android.graphics.Bitmap getBitmap(String);
- method @IntRange(from=0) public int getBitmapDimensionLimit();
+ method @IntRange(from=1) public int getBitmapDimensionLimit();
method @NonNull public android.media.MediaDescription getDescription();
method public long getLong(String);
method public android.media.Rating getRating(String);
@@ -26458,7 +26458,7 @@
method public android.media.MediaMetadata.Builder putRating(String, android.media.Rating);
method public android.media.MediaMetadata.Builder putString(String, String);
method public android.media.MediaMetadata.Builder putText(String, CharSequence);
- method @NonNull public android.media.MediaMetadata.Builder setBitmapDimensionLimit(int);
+ method @NonNull public android.media.MediaMetadata.Builder setBitmapDimensionLimit(@IntRange(from=1) int);
}
@Deprecated public abstract class MediaMetadataEditor {
diff --git a/api/module-lib-current.txt b/api/module-lib-current.txt
index 2d24d5b..dc92b52 100644
--- a/api/module-lib-current.txt
+++ b/api/module-lib-current.txt
@@ -53,6 +53,10 @@
field public static final int FLAG_FROM_KEY = 4096; // 0x1000
}
+ public class MediaMetadataRetriever implements java.lang.AutoCloseable {
+ field public static final int METADATA_KEY_VIDEO_CODEC_MIME_TYPE = 40; // 0x28
+ }
+
@Deprecated public final class MediaParceledListSlice<T extends android.os.Parcelable> implements android.os.Parcelable {
ctor @Deprecated public MediaParceledListSlice(@NonNull java.util.List<T>);
method @Deprecated public int describeContents();
diff --git a/api/system-current.txt b/api/system-current.txt
index 2919f13..1404f7e 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -38,6 +38,7 @@
field public static final String BIND_EXTERNAL_STORAGE_SERVICE = "android.permission.BIND_EXTERNAL_STORAGE_SERVICE";
field public static final String BIND_IMS_SERVICE = "android.permission.BIND_IMS_SERVICE";
field public static final String BIND_KEYGUARD_APPWIDGET = "android.permission.BIND_KEYGUARD_APPWIDGET";
+ field public static final String BIND_MUSIC_RECOGNITION_SERVICE = "android.permission.BIND_MUSIC_RECOGNITION_SERVICE";
field public static final String BIND_NETWORK_RECOMMENDATION_SERVICE = "android.permission.BIND_NETWORK_RECOMMENDATION_SERVICE";
field public static final String BIND_NOTIFICATION_ASSISTANT_SERVICE = "android.permission.BIND_NOTIFICATION_ASSISTANT_SERVICE";
field public static final String BIND_PHONE_ACCOUNT_SUGGESTION_SERVICE = "android.permission.BIND_PHONE_ACCOUNT_SUGGESTION_SERVICE";
@@ -120,6 +121,7 @@
field public static final String MANAGE_DEBUGGING = "android.permission.MANAGE_DEBUGGING";
field public static final String MANAGE_FACTORY_RESET_PROTECTION = "android.permission.MANAGE_FACTORY_RESET_PROTECTION";
field public static final String MANAGE_IPSEC_TUNNELS = "android.permission.MANAGE_IPSEC_TUNNELS";
+ field public static final String MANAGE_MUSIC_RECOGNITION = "android.permission.MANAGE_MUSIC_RECOGNITION";
field public static final String MANAGE_ONE_TIME_PERMISSION_SESSIONS = "android.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS";
field public static final String MANAGE_ROLE_HOLDERS = "android.permission.MANAGE_ROLE_HOLDERS";
field public static final String MANAGE_ROLLBACKS = "android.permission.MANAGE_ROLLBACKS";
@@ -4617,6 +4619,58 @@
}
+package android.media.musicrecognition {
+
+ public class MusicRecognitionManager {
+ method @RequiresPermission(android.Manifest.permission.MANAGE_MUSIC_RECOGNITION) public void beginStreamingSearch(@NonNull android.media.musicrecognition.RecognitionRequest, @NonNull java.util.concurrent.Executor, @NonNull android.media.musicrecognition.MusicRecognitionManager.RecognitionCallback);
+ field public static final int RECOGNITION_FAILED_AUDIO_UNAVAILABLE = 7; // 0x7
+ field public static final int RECOGNITION_FAILED_NOT_FOUND = 1; // 0x1
+ field public static final int RECOGNITION_FAILED_NO_CONNECTIVITY = 2; // 0x2
+ field public static final int RECOGNITION_FAILED_SERVICE_KILLED = 5; // 0x5
+ field public static final int RECOGNITION_FAILED_SERVICE_UNAVAILABLE = 3; // 0x3
+ field public static final int RECOGNITION_FAILED_TIMEOUT = 6; // 0x6
+ field public static final int RECOGNITION_FAILED_UNKNOWN = -1; // 0xffffffff
+ }
+
+ public static interface MusicRecognitionManager.RecognitionCallback {
+ method public void onAudioStreamClosed();
+ method public void onRecognitionFailed(@NonNull android.media.musicrecognition.RecognitionRequest, int);
+ method public void onRecognitionSucceeded(@NonNull android.media.musicrecognition.RecognitionRequest, @NonNull android.media.MediaMetadata, @Nullable android.os.Bundle);
+ }
+
+ public abstract class MusicRecognitionService extends android.app.Service {
+ ctor public MusicRecognitionService();
+ method public abstract void onRecognize(@NonNull android.os.ParcelFileDescriptor, @NonNull android.media.AudioFormat, @NonNull android.media.musicrecognition.MusicRecognitionService.Callback);
+ }
+
+ public static interface MusicRecognitionService.Callback {
+ method public void onRecognitionFailed(int);
+ method public void onRecognitionSucceeded(@NonNull android.media.MediaMetadata, @Nullable android.os.Bundle);
+ }
+
+ public final class RecognitionRequest implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public android.media.AudioAttributes getAudioAttributes();
+ method @NonNull public android.media.AudioFormat getAudioFormat();
+ method public int getCaptureSession();
+ method public int getIgnoreBeginningFrames();
+ method public int getMaxAudioLengthSeconds();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.media.musicrecognition.RecognitionRequest> CREATOR;
+ }
+
+ public static final class RecognitionRequest.Builder {
+ ctor public RecognitionRequest.Builder();
+ method @NonNull public android.media.musicrecognition.RecognitionRequest build();
+ method @NonNull public android.media.musicrecognition.RecognitionRequest.Builder setAudioAttributes(@NonNull android.media.AudioAttributes);
+ method @NonNull public android.media.musicrecognition.RecognitionRequest.Builder setAudioFormat(@NonNull android.media.AudioFormat);
+ method @NonNull public android.media.musicrecognition.RecognitionRequest.Builder setCaptureSession(int);
+ method @NonNull public android.media.musicrecognition.RecognitionRequest.Builder setIgnoreBeginningFrames(int);
+ method @NonNull public android.media.musicrecognition.RecognitionRequest.Builder setMaxAudioLengthSeconds(int);
+ }
+
+}
+
package android.media.session {
public final class MediaSessionManager {
@@ -11500,6 +11554,7 @@
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean isIccLockEnabled();
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isIdle();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isLteCdmaEvdoGsmWcdmaEnabled();
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isMobileDataPolicyEnabled(int);
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isOffhook();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isOpportunisticNetworkEnabled();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isPotentialEmergencyNumber(@NonNull String);
@@ -11530,6 +11585,7 @@
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataActivationState(int);
method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataEnabled(int, boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataRoamingEnabled(boolean);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setMobileDataPolicyEnabledStatus(int, boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setMultiSimCarrierRestriction(boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setOpportunisticNetworkState(boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setPreferredNetworkTypeBitmask(long);
@@ -11580,6 +11636,8 @@
field public static final int INVALID_EMERGENCY_NUMBER_DB_VERSION = -1; // 0xffffffff
field public static final int KEY_TYPE_EPDG = 1; // 0x1
field public static final int KEY_TYPE_WLAN = 2; // 0x2
+ field public static final int MOBILE_DATA_POLICY_DATA_ON_NON_DEFAULT_DURING_VOICE_CALL = 1; // 0x1
+ field public static final int MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED = 2; // 0x2
field public static final long NETWORK_TYPE_BITMASK_1xRTT = 64L; // 0x40L
field public static final long NETWORK_TYPE_BITMASK_CDMA = 8L; // 0x8L
field public static final long NETWORK_TYPE_BITMASK_EDGE = 2L; // 0x2L
diff --git a/api/test-current.txt b/api/test-current.txt
index a27268d..7666337 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -23,6 +23,7 @@
field public static final String REMOVE_TASKS = "android.permission.REMOVE_TASKS";
field public static final String RESET_APP_ERRORS = "android.permission.RESET_APP_ERRORS";
field public static final String SUSPEND_APPS = "android.permission.SUSPEND_APPS";
+ field public static final String TEST_BIOMETRIC = "android.permission.TEST_BIOMETRIC";
field public static final String TEST_MANAGE_ROLLBACKS = "android.permission.TEST_MANAGE_ROLLBACKS";
field public static final String UPGRADE_RUNTIME_PERMISSIONS = "android.permission.UPGRADE_RUNTIME_PERMISSIONS";
field public static final String WRITE_DEVICE_CONFIG = "android.permission.WRITE_DEVICE_CONFIG";
@@ -1223,6 +1224,35 @@
}
+package android.hardware.biometrics {
+
+ public class BiometricManager {
+ method @NonNull @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public android.hardware.biometrics.BiometricTestSession getTestSession();
+ }
+
+ public class BiometricTestSession implements java.lang.AutoCloseable {
+ method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void authenticateReject(int, int);
+ method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void authenticateSuccess(int, int);
+ method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void close();
+ method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void enableTestHal(int, boolean);
+ method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void enrollFinish(int, int);
+ method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void enrollStart(int, int);
+ method @NonNull @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public java.util.List<android.hardware.biometrics.SensorProperties> getSensorProperties();
+ method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void internalCleanup(int, int);
+ method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void notifyAcquired(int, int);
+ method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void notifyError(int, int);
+ }
+
+ public class SensorProperties {
+ method public int getSensorId();
+ method public int getSensorStrength();
+ field public static final int STRENGTH_CONVENIENCE = 0; // 0x0
+ field public static final int STRENGTH_STRONG = 2; // 0x2
+ field public static final int STRENGTH_WEAK = 1; // 0x1
+ }
+
+}
+
package android.hardware.camera2 {
public abstract class CameraDevice implements java.lang.AutoCloseable {
@@ -1328,6 +1358,14 @@
}
+package android.hardware.fingerprint {
+
+ @Deprecated public class FingerprintManager {
+ method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public android.hardware.biometrics.BiometricTestSession getTestSession();
+ }
+
+}
+
package android.hardware.hdmi {
public final class HdmiControlManager {
@@ -1719,7 +1757,6 @@
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void getCurrentLocation(@NonNull android.location.LocationRequest, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.location.Location>);
method @NonNull public String[] getIgnoreSettingsWhitelist();
method @Deprecated @Nullable @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public java.util.List<java.lang.String> getProviderPackages(@NonNull String);
- method @NonNull public java.util.List<android.location.LocationRequest> getTestProviderCurrentRequests(String);
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.LocationListener);
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull android.app.PendingIntent);
@@ -2035,6 +2072,57 @@
}
+package android.media.musicrecognition {
+
+ public class MusicRecognitionManager {
+ field public static final int RECOGNITION_FAILED_AUDIO_UNAVAILABLE = 7; // 0x7
+ field public static final int RECOGNITION_FAILED_NOT_FOUND = 1; // 0x1
+ field public static final int RECOGNITION_FAILED_NO_CONNECTIVITY = 2; // 0x2
+ field public static final int RECOGNITION_FAILED_SERVICE_KILLED = 5; // 0x5
+ field public static final int RECOGNITION_FAILED_SERVICE_UNAVAILABLE = 3; // 0x3
+ field public static final int RECOGNITION_FAILED_TIMEOUT = 6; // 0x6
+ field public static final int RECOGNITION_FAILED_UNKNOWN = -1; // 0xffffffff
+ }
+
+ public static interface MusicRecognitionManager.RecognitionCallback {
+ method public void onAudioStreamClosed();
+ method public void onRecognitionFailed(@NonNull android.media.musicrecognition.RecognitionRequest, int);
+ method public void onRecognitionSucceeded(@NonNull android.media.musicrecognition.RecognitionRequest, @NonNull android.media.MediaMetadata, @Nullable android.os.Bundle);
+ }
+
+ public abstract class MusicRecognitionService extends android.app.Service {
+ ctor public MusicRecognitionService();
+ method public abstract void onRecognize(@NonNull android.os.ParcelFileDescriptor, @NonNull android.media.AudioFormat, @NonNull android.media.musicrecognition.MusicRecognitionService.Callback);
+ }
+
+ public static interface MusicRecognitionService.Callback {
+ method public void onRecognitionFailed(int);
+ method public void onRecognitionSucceeded(@NonNull android.media.MediaMetadata, @Nullable android.os.Bundle);
+ }
+
+ public final class RecognitionRequest implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public android.media.AudioAttributes getAudioAttributes();
+ method @NonNull public android.media.AudioFormat getAudioFormat();
+ method public int getCaptureSession();
+ method public int getIgnoreBeginningFrames();
+ method public int getMaxAudioLengthSeconds();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.media.musicrecognition.RecognitionRequest> CREATOR;
+ }
+
+ public static final class RecognitionRequest.Builder {
+ ctor public RecognitionRequest.Builder();
+ method @NonNull public android.media.musicrecognition.RecognitionRequest build();
+ method @NonNull public android.media.musicrecognition.RecognitionRequest.Builder setAudioAttributes(@NonNull android.media.AudioAttributes);
+ method @NonNull public android.media.musicrecognition.RecognitionRequest.Builder setAudioFormat(@NonNull android.media.AudioFormat);
+ method @NonNull public android.media.musicrecognition.RecognitionRequest.Builder setCaptureSession(int);
+ method @NonNull public android.media.musicrecognition.RecognitionRequest.Builder setIgnoreBeginningFrames(int);
+ method @NonNull public android.media.musicrecognition.RecognitionRequest.Builder setMaxAudioLengthSeconds(int);
+ }
+
+}
+
package android.media.tv {
public final class TvInputManager {
@@ -4218,11 +4306,13 @@
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getEmergencyNumberDbVersion();
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getLine1AlphaTag();
method public android.util.Pair<java.lang.Integer,java.lang.Integer> getRadioHalVersion();
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isMobileDataPolicyEnabled(int);
method public boolean modifyDevicePolicyOverrideApn(@NonNull android.content.Context, int, @NonNull android.telephony.data.ApnSetting);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void refreshUiccProfile();
method @RequiresPermission("android.permission.READ_ACTIVE_EMERGENCY_SESSION") public void resetOtaEmergencyNumberDbFilePath();
method @Deprecated public void setCarrierTestOverride(String, String, String, String, String, String, String);
method public void setCarrierTestOverride(String, String, String, String, String, String, String, String, String);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setMobileDataPolicyEnabledStatus(int, boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSystemSelectionChannels(@NonNull java.util.List<android.telephony.RadioAccessSpecifier>, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSystemSelectionChannels(@NonNull java.util.List<android.telephony.RadioAccessSpecifier>);
method @RequiresPermission("android.permission.READ_ACTIVE_EMERGENCY_SESSION") public void updateOtaEmergencyNumberDbFilePath(@NonNull android.os.ParcelFileDescriptor);
@@ -4231,6 +4321,8 @@
field public static final int CARRIER_PRIVILEGE_STATUS_NO_ACCESS = 0; // 0x0
field public static final int CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED = -1; // 0xffffffff
field public static final int INVALID_EMERGENCY_NUMBER_DB_VERSION = -1; // 0xffffffff
+ field public static final int MOBILE_DATA_POLICY_DATA_ON_NON_DEFAULT_DURING_VOICE_CALL = 1; // 0x1
+ field public static final int MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED = 2; // 0x2
field public static final int UNKNOWN_CARRIER_ID_LIST_VERSION = -1; // 0xffffffff
}
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 90c8788..4beb748 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -493,6 +493,8 @@
WifiConnectionStateChanged wifi_connection_state_changed = 308 [(module) = "wifi"];
HdmiCecActiveSourceChanged hdmi_cec_active_source_changed = 309 [(module) = "framework"];
HdmiCecMessageReported hdmi_cec_message_reported = 310 [(module) = "framework"];
+ AirplaneMode airplane_mode = 311 [(module) = "telephony"];
+ ModemRestart modem_restart = 312 [(module) = "telephony"];
// StatsdStats tracks platform atoms with ids upto 500.
// Update StatsdStats::kMaxPushedAtomId when atom ids here approach that value.
@@ -4466,6 +4468,7 @@
// which requires reboot and not eligible for any reboot promotion strategy
// (e.g. soft restart, notification restart).
NO_REBOOT_PROMOTION_STRATEGY_ELIGIBLE = 30;
+ REBOOT_TRIGGER_FAILURE = 31;
}
optional State state = 6;
// Possible experiment ids for monitoring this push.
@@ -10575,12 +10578,48 @@
}
/**
+ * Push information about usage of airplane mode.
+ *
+ * Logged from:
+ * frameworks/opt/telephony/src/java/com/android/internal/telephony/metrics/AirplaneModeStats.java
+ */
+message AirplaneMode {
+ // Status of airplane mode
+ optional bool is_enabled = 1;
+
+ // When is_enabled is false, indicates if this was a very short airplane mode toggle
+ // (i.e. airplane mode was disabled after less than 10 seconds from enablement).
+ optional bool short_toggle = 2;
+
+ // Carrier ID of the SIM card.
+ // See https://source.android.com/devices/tech/config/carrierid.
+ optional int32 carrier_id = 3;
+}
+
+/**
+ * Push information about modem restarts.
+ *
+ * Logged from:
+ * frameworks/opt/telephony/src/java/com/android/internal/telephony/metrics/ModemRestartStats.java
+ */
+message ModemRestart {
+ // Software version of the modem, as provided by android.os.Build.getRadioVersion().
+ optional string baseband_version = 1;
+
+ // Reason of the modem restart, as provided in the modemReset indication of IRadio HAL.
+ optional string reason = 2;
+
+ // Carrier ID of the first SIM card.
+ // See https://source.android.com/devices/tech/config/carrierid.
+ optional int32 carrier_id = 3;
+}
+
+/**
* Logs gnss stats from location service provider
*
* Pulled from:
* frameworks/base/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
*/
-
message GnssStats {
// Number of location reports since boot
optional int64 location_reports = 1;
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index 9dda248..2a37b58 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -17,9 +17,11 @@
#define DEBUG false // STOPSHIP if true
#include "Log.h"
-#include "../guardrail/StatsdStats.h"
#include "GaugeMetricProducer.h"
-#include "../stats_log_util.h"
+
+#include "guardrail/StatsdStats.h"
+#include "metrics/parsing_utils/metrics_manager_util.h"
+#include "stats_log_util.h"
using android::util::FIELD_COUNT_REPEATED;
using android::util::FIELD_TYPE_BOOL;
@@ -154,6 +156,58 @@
}
}
+bool GaugeMetricProducer::onConfigUpdatedLocked(
+ const StatsdConfig& config, const int configIndex, const int metricIndex,
+ const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
+ const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
+ const unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
+ const sp<EventMatcherWizard>& matcherWizard,
+ const vector<sp<ConditionTracker>>& allConditionTrackers,
+ const unordered_map<int64_t, int>& conditionTrackerMap, const sp<ConditionWizard>& wizard,
+ const unordered_map<int64_t, int>& metricToActivationMap,
+ unordered_map<int, vector<int>>& trackerToMetricMap,
+ unordered_map<int, vector<int>>& conditionToMetricMap,
+ unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
+ unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
+ vector<int>& metricsWithActivation) {
+ if (!MetricProducer::onConfigUpdatedLocked(
+ config, configIndex, metricIndex, allAtomMatchingTrackers,
+ oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap, matcherWizard,
+ allConditionTrackers, conditionTrackerMap, wizard, metricToActivationMap,
+ trackerToMetricMap, conditionToMetricMap, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, metricsWithActivation)) {
+ return false;
+ }
+
+ const GaugeMetric& metric = config.gauge_metric(configIndex);
+ // Update appropriate indices: mWhatMatcherIndex, mConditionIndex and MetricsManager maps.
+ if (!handleMetricWithAtomMatchingTrackers(metric.what(), metricIndex, /*enforceOneAtom=*/false,
+ allAtomMatchingTrackers, newAtomMatchingTrackerMap,
+ trackerToMetricMap, mWhatMatcherIndex)) {
+ return false;
+ }
+
+ // Need to update maps since the index changed, but mTriggerAtomId will not change.
+ int triggerTrackerIndex;
+ if (metric.has_trigger_event() &&
+ !handleMetricWithAtomMatchingTrackers(metric.trigger_event(), metricIndex,
+ /*enforceOneAtom=*/true, allAtomMatchingTrackers,
+ newAtomMatchingTrackerMap, trackerToMetricMap,
+ triggerTrackerIndex)) {
+ return false;
+ }
+
+ if (metric.has_condition() &&
+ !handleMetricWithConditions(metric.condition(), metricIndex, conditionTrackerMap,
+ metric.links(), allConditionTrackers, mConditionTrackerIndex,
+ conditionToMetricMap)) {
+ return false;
+ }
+ sp<EventMatcherWizard> tmpEventWizard = mEventMatcherWizard;
+ mEventMatcherWizard = matcherWizard;
+ return true;
+}
+
void GaugeMetricProducer::dumpStatesLocked(FILE* out, bool verbose) const {
if (mCurrentSlicedBucket == nullptr ||
mCurrentSlicedBucket->size() == 0) {
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.h b/cmds/statsd/src/metrics/GaugeMetricProducer.h
index e933d4b..9bdaac9 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.h
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.h
@@ -53,8 +53,8 @@
// This gauge metric producer first register the puller to automatically pull the gauge at the
// beginning of each bucket. If the condition is met, insert it to the bucket info. Otherwise
// proactively pull the gauge when the condition is changed to be true. Therefore, the gauge metric
-// producer always reports the guage at the earliest time of the bucket when the condition is met.
-class GaugeMetricProducer : public virtual MetricProducer, public virtual PullDataReceiver {
+// producer always reports the gauge at the earliest time of the bucket when the condition is met.
+class GaugeMetricProducer : public MetricProducer, public virtual PullDataReceiver {
public:
GaugeMetricProducer(
const ConfigKey& key, const GaugeMetric& gaugeMetric, const int conditionIndex,
@@ -142,7 +142,23 @@
void pullAndMatchEventsLocked(const int64_t timestampNs);
- const int mWhatMatcherIndex;
+ bool onConfigUpdatedLocked(
+ const StatsdConfig& config, const int configIndex, const int metricIndex,
+ const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
+ const std::unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
+ const std::unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
+ const sp<EventMatcherWizard>& matcherWizard,
+ const std::vector<sp<ConditionTracker>>& allConditionTrackers,
+ const std::unordered_map<int64_t, int>& conditionTrackerMap,
+ const sp<ConditionWizard>& wizard,
+ const std::unordered_map<int64_t, int>& metricToActivationMap,
+ std::unordered_map<int, std::vector<int>>& trackerToMetricMap,
+ std::unordered_map<int, std::vector<int>>& conditionToMetricMap,
+ std::unordered_map<int, std::vector<int>>& activationAtomTrackerToMetricMap,
+ std::unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
+ std::vector<int>& metricsWithActivation) override;
+
+ int mWhatMatcherIndex;
sp<EventMatcherWizard> mEventMatcherWizard;
@@ -209,6 +225,8 @@
FRIEND_TEST(GaugeMetricProducerTest_PartialBucket, TestPushedEvents);
FRIEND_TEST(GaugeMetricProducerTest_PartialBucket, TestPulled);
+
+ FRIEND_TEST(ConfigUpdateTest, TestUpdateGaugeMetrics);
};
} // namespace statsd
diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h
index 4360010..18e62d2 100644
--- a/cmds/statsd/src/metrics/MetricProducer.h
+++ b/cmds/statsd/src/metrics/MetricProducer.h
@@ -568,6 +568,7 @@
FRIEND_TEST(ConfigUpdateTest, TestUpdateMetricActivations);
FRIEND_TEST(ConfigUpdateTest, TestUpdateCountMetrics);
FRIEND_TEST(ConfigUpdateTest, TestUpdateEventMetrics);
+ FRIEND_TEST(ConfigUpdateTest, TestUpdateGaugeMetrics);
FRIEND_TEST(ConfigUpdateTest, TestUpdateMetricsMultipleTypes);
};
diff --git a/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp b/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp
index 5ff6975..93795d4 100644
--- a/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp
+++ b/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp
@@ -531,10 +531,69 @@
return false;
}
}
- // TODO: determine update status for count, gauge, value, duration metrics.
+
+ for (int i = 0; i < config.gauge_metric_size(); i++, metricIndex++) {
+ const GaugeMetric& metric = config.gauge_metric(i);
+ set<int64_t> conditionDependencies;
+ if (metric.has_condition()) {
+ conditionDependencies.insert(metric.condition());
+ }
+ set<int64_t> matcherDependencies;
+ matcherDependencies.insert(metric.what());
+ if (metric.has_trigger_event()) {
+ matcherDependencies.insert(metric.trigger_event());
+ }
+ if (!determineMetricUpdateStatus(
+ config, metric, metric.id(), METRIC_TYPE_GAUGE, matcherDependencies,
+ conditionDependencies, ::google::protobuf::RepeatedField<int64_t>(),
+ metric.links(), oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
+ replacedMatchers, replacedConditions, replacedStates,
+ metricsToUpdate[metricIndex])) {
+ return false;
+ }
+ }
+ // TODO: determine update status for value, duration metrics.
return true;
}
+// Called when a metric is preserved during a config update. Finds the metric in oldMetricProducers
+// and calls onConfigUpdated to update all indices.
+optional<sp<MetricProducer>> updateMetric(
+ const StatsdConfig& config, const int configIndex, const int metricIndex,
+ const int64_t metricId, const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
+ const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
+ const unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
+ const sp<EventMatcherWizard>& matcherWizard,
+ const vector<sp<ConditionTracker>>& allConditionTrackers,
+ const unordered_map<int64_t, int>& conditionTrackerMap, const sp<ConditionWizard>& wizard,
+ const unordered_map<int64_t, int>& oldMetricProducerMap,
+ const vector<sp<MetricProducer>>& oldMetricProducers,
+ const unordered_map<int64_t, int>& metricToActivationMap,
+ unordered_map<int, vector<int>>& trackerToMetricMap,
+ unordered_map<int, vector<int>>& conditionToMetricMap,
+ unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
+ unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
+ vector<int>& metricsWithActivation) {
+ const auto& oldMetricProducerIt = oldMetricProducerMap.find(metricId);
+ if (oldMetricProducerIt == oldMetricProducerMap.end()) {
+ ALOGE("Could not find Metric %lld in the previous config, but expected it "
+ "to be there",
+ (long long)metricId);
+ return nullopt;
+ }
+ const int oldIndex = oldMetricProducerIt->second;
+ sp<MetricProducer> producer = oldMetricProducers[oldIndex];
+ if (!producer->onConfigUpdated(config, configIndex, metricIndex, allAtomMatchingTrackers,
+ oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap,
+ matcherWizard, allConditionTrackers, conditionTrackerMap, wizard,
+ metricToActivationMap, trackerToMetricMap, conditionToMetricMap,
+ activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, metricsWithActivation)) {
+ return nullopt;
+ }
+ return {producer};
+}
+
bool updateMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseNs,
const int64_t currentTimeNs, const sp<StatsPullerManager>& pullerManager,
const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
@@ -588,41 +647,29 @@
// Now, perform the update. Must iterate the metric types in the same order
int metricIndex = 0;
for (int i = 0; i < config.count_metric_size(); i++, metricIndex++) {
- newMetricProducerMap[config.count_metric(i).id()] = metricIndex;
const CountMetric& metric = config.count_metric(i);
+ newMetricProducerMap[metric.id()] = metricIndex;
+ optional<sp<MetricProducer>> producer;
switch (metricsToUpdate[metricIndex]) {
case UPDATE_PRESERVE: {
- const auto& oldMetricProducerIt = oldMetricProducerMap.find(metric.id());
- if (oldMetricProducerIt == oldMetricProducerMap.end()) {
- ALOGE("Could not find Metric %lld in the previous config, but expected it "
- "to be there",
- (long long)metric.id());
- return false;
- }
- const int oldIndex = oldMetricProducerIt->second;
- sp<MetricProducer> producer = oldMetricProducers[oldIndex];
- producer->onConfigUpdated(
- config, i, metricIndex, allAtomMatchingTrackers, oldAtomMatchingTrackerMap,
- newAtomMatchingTrackerMap, matcherWizard, allConditionTrackers,
- conditionTrackerMap, wizard, metricToActivationMap, trackerToMetricMap,
+ producer = updateMetric(
+ config, i, metricIndex, metric.id(), allAtomMatchingTrackers,
+ oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap, matcherWizard,
+ allConditionTrackers, conditionTrackerMap, wizard, oldMetricProducerMap,
+ oldMetricProducers, metricToActivationMap, trackerToMetricMap,
conditionToMetricMap, activationAtomTrackerToMetricMap,
deactivationAtomTrackerToMetricMap, metricsWithActivation);
- newMetricProducers.push_back(producer);
break;
}
case UPDATE_REPLACE:
case UPDATE_NEW: {
- sp<MetricProducer> producer = createCountMetricProducerAndUpdateMetadata(
+ producer = createCountMetricProducerAndUpdateMetadata(
key, config, timeBaseNs, currentTimeNs, metric, metricIndex,
allAtomMatchingTrackers, newAtomMatchingTrackerMap, allConditionTrackers,
conditionTrackerMap, initialConditionCache, wizard, stateAtomIdMap,
allStateGroupMaps, metricToActivationMap, trackerToMetricMap,
conditionToMetricMap, activationAtomTrackerToMetricMap,
deactivationAtomTrackerToMetricMap, metricsWithActivation);
- if (producer == nullptr) {
- return false;
- }
- newMetricProducers.push_back(producer);
break;
}
default: {
@@ -631,42 +678,34 @@
return false;
}
}
+ if (!producer) {
+ return false;
+ }
+ newMetricProducers.push_back(producer.value());
}
for (int i = 0; i < config.event_metric_size(); i++, metricIndex++) {
newMetricProducerMap[config.event_metric(i).id()] = metricIndex;
const EventMetric& metric = config.event_metric(i);
+ optional<sp<MetricProducer>> producer;
switch (metricsToUpdate[metricIndex]) {
case UPDATE_PRESERVE: {
- const auto& oldMetricProducerIt = oldMetricProducerMap.find(metric.id());
- if (oldMetricProducerIt == oldMetricProducerMap.end()) {
- ALOGE("Could not find Metric %lld in the previous config, but expected it "
- "to be there",
- (long long)metric.id());
- return false;
- }
- const int oldIndex = oldMetricProducerIt->second;
- sp<MetricProducer> producer = oldMetricProducers[oldIndex];
- producer->onConfigUpdated(
- config, i, metricIndex, allAtomMatchingTrackers, oldAtomMatchingTrackerMap,
- newAtomMatchingTrackerMap, matcherWizard, allConditionTrackers,
- conditionTrackerMap, wizard, metricToActivationMap, trackerToMetricMap,
+ producer = updateMetric(
+ config, i, metricIndex, metric.id(), allAtomMatchingTrackers,
+ oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap, matcherWizard,
+ allConditionTrackers, conditionTrackerMap, wizard, oldMetricProducerMap,
+ oldMetricProducers, metricToActivationMap, trackerToMetricMap,
conditionToMetricMap, activationAtomTrackerToMetricMap,
deactivationAtomTrackerToMetricMap, metricsWithActivation);
- newMetricProducers.push_back(producer);
break;
}
case UPDATE_REPLACE:
case UPDATE_NEW: {
- sp<MetricProducer> producer = createEventMetricProducerAndUpdateMetadata(
+ producer = createEventMetricProducerAndUpdateMetadata(
key, config, timeBaseNs, metric, metricIndex, allAtomMatchingTrackers,
newAtomMatchingTrackerMap, allConditionTrackers, conditionTrackerMap,
initialConditionCache, wizard, metricToActivationMap, trackerToMetricMap,
conditionToMetricMap, activationAtomTrackerToMetricMap,
deactivationAtomTrackerToMetricMap, metricsWithActivation);
- if (producer == nullptr) {
- return false;
- }
- newMetricProducers.push_back(producer);
break;
}
default: {
@@ -675,8 +714,49 @@
return false;
}
}
+ if (!producer) {
+ return false;
+ }
+ newMetricProducers.push_back(producer.value());
}
- // TODO: perform update for count, gauge, value, duration metric.
+ for (int i = 0; i < config.gauge_metric_size(); i++, metricIndex++) {
+ const GaugeMetric& metric = config.gauge_metric(i);
+ newMetricProducerMap[metric.id()] = metricIndex;
+ optional<sp<MetricProducer>> producer;
+ switch (metricsToUpdate[metricIndex]) {
+ case UPDATE_PRESERVE: {
+ producer = updateMetric(
+ config, i, metricIndex, metric.id(), allAtomMatchingTrackers,
+ oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap, matcherWizard,
+ allConditionTrackers, conditionTrackerMap, wizard, oldMetricProducerMap,
+ oldMetricProducers, metricToActivationMap, trackerToMetricMap,
+ conditionToMetricMap, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, metricsWithActivation);
+ break;
+ }
+ case UPDATE_REPLACE:
+ case UPDATE_NEW: {
+ producer = createGaugeMetricProducerAndUpdateMetadata(
+ key, config, timeBaseNs, currentTimeNs, pullerManager, metric, metricIndex,
+ allAtomMatchingTrackers, newAtomMatchingTrackerMap, allConditionTrackers,
+ conditionTrackerMap, initialConditionCache, wizard, matcherWizard,
+ metricToActivationMap, trackerToMetricMap, conditionToMetricMap,
+ activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
+ metricsWithActivation);
+ break;
+ }
+ default: {
+ ALOGE("Metric \"%lld\" update state is unknown. This should never happen",
+ (long long)metric.id());
+ return false;
+ }
+ }
+ if (!producer) {
+ return false;
+ }
+ newMetricProducers.push_back(producer.value());
+ }
+ // TODO: perform update for value, duration metric.
const set<int> atomsAllowedFromAnyUid(config.whitelisted_atom_ids().begin(),
config.whitelisted_atom_ids().end());
diff --git a/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp
index 98c6222..34e265c 100644
--- a/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp
+++ b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp
@@ -348,7 +348,7 @@
return true;
}
-sp<MetricProducer> createCountMetricProducerAndUpdateMetadata(
+optional<sp<MetricProducer>> createCountMetricProducerAndUpdateMetadata(
const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseNs,
const int64_t currentTimeNs, const CountMetric& metric, const int metricIndex,
const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
@@ -366,14 +366,14 @@
vector<int>& metricsWithActivation) {
if (!metric.has_id() || !metric.has_what()) {
ALOGW("cannot find metric id or \"what\" in CountMetric \"%lld\"", (long long)metric.id());
- return nullptr;
+ return nullopt;
}
int trackerIndex;
if (!handleMetricWithAtomMatchingTrackers(metric.what(), metricIndex,
metric.has_dimensions_in_what(),
allAtomMatchingTrackers, atomMatchingTrackerMap,
trackerToMetricMap, trackerIndex)) {
- return nullptr;
+ return nullopt;
}
int conditionIndex = -1;
@@ -381,12 +381,12 @@
if (!handleMetricWithConditions(metric.condition(), metricIndex, conditionTrackerMap,
metric.links(), allConditionTrackers, conditionIndex,
conditionToMetricMap)) {
- return nullptr;
+ return nullopt;
}
} else {
if (metric.links_size() > 0) {
ALOGW("metrics has a MetricConditionLink but doesn't have a condition");
- return nullptr;
+ return nullopt;
}
}
@@ -395,12 +395,12 @@
if (metric.slice_by_state_size() > 0) {
if (!handleMetricWithStates(config, metric.slice_by_state(), stateAtomIdMap,
allStateGroupMaps, slicedStateAtoms, stateGroupMap)) {
- return nullptr;
+ return nullopt;
}
} else {
if (metric.state_link_size() > 0) {
ALOGW("CountMetric has a MetricStateLink but doesn't have a slice_by_state");
- return nullptr;
+ return nullopt;
}
}
@@ -410,20 +410,20 @@
atomMatchingTrackerMap, activationAtomTrackerToMetricMap,
deactivationAtomTrackerToMetricMap, metricsWithActivation,
eventActivationMap, eventDeactivationMap)) {
- return nullptr;
+ return nullopt;
}
uint64_t metricHash;
if (!getMetricProtoHash(config, metric, metric.id(), metricToActivationMap, metricHash)) {
- return nullptr;
+ return nullopt;
}
- return new CountMetricProducer(key, metric, conditionIndex, initialConditionCache, wizard,
- metricHash, timeBaseNs, currentTimeNs, eventActivationMap,
- eventDeactivationMap, slicedStateAtoms, stateGroupMap);
+ return {new CountMetricProducer(key, metric, conditionIndex, initialConditionCache, wizard,
+ metricHash, timeBaseNs, currentTimeNs, eventActivationMap,
+ eventDeactivationMap, slicedStateAtoms, stateGroupMap)};
}
-sp<MetricProducer> createEventMetricProducerAndUpdateMetadata(
+optional<sp<MetricProducer>> createEventMetricProducerAndUpdateMetadata(
const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseNs,
const EventMetric& metric, const int metricIndex,
const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
@@ -439,13 +439,13 @@
vector<int>& metricsWithActivation) {
if (!metric.has_id() || !metric.has_what()) {
ALOGW("cannot find the metric name or what in config");
- return nullptr;
+ return nullopt;
}
int trackerIndex;
if (!handleMetricWithAtomMatchingTrackers(metric.what(), metricIndex, false,
allAtomMatchingTrackers, atomMatchingTrackerMap,
trackerToMetricMap, trackerIndex)) {
- return nullptr;
+ return nullopt;
}
int conditionIndex = -1;
@@ -453,12 +453,12 @@
if (!handleMetricWithConditions(metric.condition(), metricIndex, conditionTrackerMap,
metric.links(), allConditionTrackers, conditionIndex,
conditionToMetricMap)) {
- return nullptr;
+ return nullopt;
}
} else {
if (metric.links_size() > 0) {
ALOGW("metrics has a MetricConditionLink but doesn't have a condition");
- return nullptr;
+ return nullopt;
}
}
@@ -472,12 +472,125 @@
uint64_t metricHash;
if (!getMetricProtoHash(config, metric, metric.id(), metricToActivationMap, metricHash)) {
- return nullptr;
+ return nullopt;
}
- return new EventMetricProducer(key, metric, conditionIndex, initialConditionCache, wizard,
- metricHash, timeBaseNs, eventActivationMap,
- eventDeactivationMap);
+ return {new EventMetricProducer(key, metric, conditionIndex, initialConditionCache, wizard,
+ metricHash, timeBaseNs, eventActivationMap,
+ eventDeactivationMap)};
+}
+
+optional<sp<MetricProducer>> createGaugeMetricProducerAndUpdateMetadata(
+ const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseNs,
+ const int64_t currentTimeNs, const sp<StatsPullerManager>& pullerManager,
+ const GaugeMetric& metric, const int metricIndex,
+ const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
+ const unordered_map<int64_t, int>& atomMatchingTrackerMap,
+ vector<sp<ConditionTracker>>& allConditionTrackers,
+ const unordered_map<int64_t, int>& conditionTrackerMap,
+ const vector<ConditionState>& initialConditionCache, const sp<ConditionWizard>& wizard,
+ const sp<EventMatcherWizard>& matcherWizard,
+ const unordered_map<int64_t, int>& metricToActivationMap,
+ unordered_map<int, vector<int>>& trackerToMetricMap,
+ unordered_map<int, vector<int>>& conditionToMetricMap,
+ unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
+ unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
+ vector<int>& metricsWithActivation) {
+ if (!metric.has_id() || !metric.has_what()) {
+ ALOGW("cannot find metric id or \"what\" in GaugeMetric \"%lld\"", (long long)metric.id());
+ return nullopt;
+ }
+
+ if ((!metric.gauge_fields_filter().has_include_all() ||
+ (metric.gauge_fields_filter().include_all() == false)) &&
+ !hasLeafNode(metric.gauge_fields_filter().fields())) {
+ ALOGW("Incorrect field filter setting in GaugeMetric %lld", (long long)metric.id());
+ return nullopt;
+ }
+ if ((metric.gauge_fields_filter().has_include_all() &&
+ metric.gauge_fields_filter().include_all() == true) &&
+ hasLeafNode(metric.gauge_fields_filter().fields())) {
+ ALOGW("Incorrect field filter setting in GaugeMetric %lld", (long long)metric.id());
+ return nullopt;
+ }
+
+ int trackerIndex;
+ if (!handleMetricWithAtomMatchingTrackers(metric.what(), metricIndex,
+ metric.has_dimensions_in_what(),
+ allAtomMatchingTrackers, atomMatchingTrackerMap,
+ trackerToMetricMap, trackerIndex)) {
+ return nullopt;
+ }
+
+ sp<AtomMatchingTracker> atomMatcher = allAtomMatchingTrackers.at(trackerIndex);
+ // For GaugeMetric atom, it should be simple matcher with one tagId.
+ if (atomMatcher->getAtomIds().size() != 1) {
+ return nullopt;
+ }
+ int atomTagId = *(atomMatcher->getAtomIds().begin());
+ int pullTagId = pullerManager->PullerForMatcherExists(atomTagId) ? atomTagId : -1;
+
+ int triggerTrackerIndex;
+ int triggerAtomId = -1;
+ if (metric.has_trigger_event()) {
+ if (pullTagId == -1) {
+ ALOGW("Pull atom not specified for trigger");
+ return nullopt;
+ }
+ // trigger_event should be used with FIRST_N_SAMPLES
+ if (metric.sampling_type() != GaugeMetric::FIRST_N_SAMPLES) {
+ ALOGW("Gauge Metric with trigger event must have sampling type FIRST_N_SAMPLES");
+ return nullopt;
+ }
+ if (!handleMetricWithAtomMatchingTrackers(metric.trigger_event(), metricIndex,
+ /*enforceOneAtom=*/true, allAtomMatchingTrackers,
+ atomMatchingTrackerMap, trackerToMetricMap,
+ triggerTrackerIndex)) {
+ return nullopt;
+ }
+ sp<AtomMatchingTracker> triggerAtomMatcher =
+ allAtomMatchingTrackers.at(triggerTrackerIndex);
+ triggerAtomId = *(triggerAtomMatcher->getAtomIds().begin());
+ }
+
+ if (!metric.has_trigger_event() && pullTagId != -1 &&
+ metric.sampling_type() == GaugeMetric::FIRST_N_SAMPLES) {
+ ALOGW("FIRST_N_SAMPLES is only for pushed event or pull_on_trigger");
+ return nullopt;
+ }
+
+ int conditionIndex = -1;
+ if (metric.has_condition()) {
+ if (!handleMetricWithConditions(metric.condition(), metricIndex, conditionTrackerMap,
+ metric.links(), allConditionTrackers, conditionIndex,
+ conditionToMetricMap)) {
+ return nullopt;
+ }
+ } else {
+ if (metric.links_size() > 0) {
+ ALOGW("metrics has a MetricConditionLink but doesn't have a condition");
+ return nullopt;
+ }
+ }
+
+ unordered_map<int, shared_ptr<Activation>> eventActivationMap;
+ unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
+ if (!handleMetricActivation(config, metric.id(), metricIndex, metricToActivationMap,
+ atomMatchingTrackerMap, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, metricsWithActivation,
+ eventActivationMap, eventDeactivationMap)) {
+ return nullopt;
+ }
+
+ uint64_t metricHash;
+ if (!getMetricProtoHash(config, metric, metric.id(), metricToActivationMap, metricHash)) {
+ return nullopt;
+ }
+
+ return {new GaugeMetricProducer(key, metric, conditionIndex, initialConditionCache, wizard,
+ metricHash, trackerIndex, matcherWizard, pullTagId,
+ triggerAtomId, atomTagId, timeBaseNs, currentTimeNs,
+ pullerManager, eventActivationMap, eventDeactivationMap)};
}
bool initAtomMatchingTrackers(const StatsdConfig& config, const sp<UidMap>& uidMap,
@@ -628,17 +741,17 @@
int metricIndex = allMetricProducers.size();
const CountMetric& metric = config.count_metric(i);
metricMap.insert({metric.id(), metricIndex});
- sp<MetricProducer> producer = createCountMetricProducerAndUpdateMetadata(
+ optional<sp<MetricProducer>> producer = createCountMetricProducerAndUpdateMetadata(
key, config, timeBaseTimeNs, currentTimeNs, metric, metricIndex,
allAtomMatchingTrackers, atomMatchingTrackerMap, allConditionTrackers,
conditionTrackerMap, initialConditionCache, wizard, stateAtomIdMap,
allStateGroupMaps, metricToActivationMap, trackerToMetricMap, conditionToMetricMap,
activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
metricsWithActivation);
- if (producer == nullptr) {
+ if (!producer) {
return false;
}
- allMetricProducers.push_back(producer);
+ allMetricProducers.push_back(producer.value());
}
// build DurationMetricProducer
@@ -762,16 +875,16 @@
int metricIndex = allMetricProducers.size();
const EventMetric& metric = config.event_metric(i);
metricMap.insert({metric.id(), metricIndex});
- sp<MetricProducer> producer = createEventMetricProducerAndUpdateMetadata(
+ optional<sp<MetricProducer>> producer = createEventMetricProducerAndUpdateMetadata(
key, config, timeBaseTimeNs, metric, metricIndex, allAtomMatchingTrackers,
atomMatchingTrackerMap, allConditionTrackers, conditionTrackerMap,
initialConditionCache, wizard, metricToActivationMap, trackerToMetricMap,
conditionToMetricMap, activationAtomTrackerToMetricMap,
deactivationAtomTrackerToMetricMap, metricsWithActivation);
- if (producer == nullptr) {
+ if (!producer) {
return false;
}
- allMetricProducers.push_back(producer);
+ allMetricProducers.push_back(producer.value());
}
// build ValueMetricProducer
@@ -871,104 +984,20 @@
// Gauge metrics.
for (int i = 0; i < config.gauge_metric_size(); i++) {
- const GaugeMetric& metric = config.gauge_metric(i);
- if (!metric.has_what()) {
- ALOGW("cannot find \"what\" in GaugeMetric \"%lld\"", (long long)metric.id());
- return false;
- }
-
- if ((!metric.gauge_fields_filter().has_include_all() ||
- (metric.gauge_fields_filter().include_all() == false)) &&
- !hasLeafNode(metric.gauge_fields_filter().fields())) {
- ALOGW("Incorrect field filter setting in GaugeMetric %lld", (long long)metric.id());
- return false;
- }
- if ((metric.gauge_fields_filter().has_include_all() &&
- metric.gauge_fields_filter().include_all() == true) &&
- hasLeafNode(metric.gauge_fields_filter().fields())) {
- ALOGW("Incorrect field filter setting in GaugeMetric %lld", (long long)metric.id());
- return false;
- }
-
int metricIndex = allMetricProducers.size();
+ const GaugeMetric& metric = config.gauge_metric(i);
metricMap.insert({metric.id(), metricIndex});
- int trackerIndex;
- if (!handleMetricWithAtomMatchingTrackers(metric.what(), metricIndex,
- metric.has_dimensions_in_what(),
- allAtomMatchingTrackers, atomMatchingTrackerMap,
- trackerToMetricMap, trackerIndex)) {
- return false;
- }
-
- sp<AtomMatchingTracker> atomMatcher = allAtomMatchingTrackers.at(trackerIndex);
- // For GaugeMetric atom, it should be simple matcher with one tagId.
- if (atomMatcher->getAtomIds().size() != 1) {
- return false;
- }
- int atomTagId = *(atomMatcher->getAtomIds().begin());
- int pullTagId = pullerManager->PullerForMatcherExists(atomTagId) ? atomTagId : -1;
-
- int triggerTrackerIndex;
- int triggerAtomId = -1;
- if (metric.has_trigger_event()) {
- if (pullTagId == -1) {
- ALOGW("Pull atom not specified for trigger");
- return false;
- }
- // event_trigger should be used with FIRST_N_SAMPLES
- if (metric.sampling_type() != GaugeMetric::FIRST_N_SAMPLES) {
- return false;
- }
- if (!handleMetricWithAtomMatchingTrackers(
- metric.trigger_event(), metricIndex, /*enforceOneAtom=*/true,
- allAtomMatchingTrackers, atomMatchingTrackerMap, trackerToMetricMap,
- triggerTrackerIndex)) {
- return false;
- }
- sp<AtomMatchingTracker> triggerAtomMatcher =
- allAtomMatchingTrackers.at(triggerTrackerIndex);
- triggerAtomId = *(triggerAtomMatcher->getAtomIds().begin());
- }
-
- if (!metric.has_trigger_event() && pullTagId != -1 &&
- metric.sampling_type() == GaugeMetric::FIRST_N_SAMPLES) {
- ALOGW("FIRST_N_SAMPLES is only for pushed event or pull_on_trigger");
- return false;
- }
-
- int conditionIndex = -1;
- if (metric.has_condition()) {
- bool good = handleMetricWithConditions(
- metric.condition(), metricIndex, conditionTrackerMap, metric.links(),
- allConditionTrackers, conditionIndex, conditionToMetricMap);
- if (!good) {
- return false;
- }
- } else {
- if (metric.links_size() > 0) {
- ALOGW("metrics has a MetricConditionLink but doesn't have a condition");
- return false;
- }
- }
-
- unordered_map<int, shared_ptr<Activation>> eventActivationMap;
- unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
- bool success = handleMetricActivation(
- config, metric.id(), metricIndex, metricToActivationMap, atomMatchingTrackerMap,
+ optional<sp<MetricProducer>> producer = createGaugeMetricProducerAndUpdateMetadata(
+ key, config, timeBaseTimeNs, currentTimeNs, pullerManager, metric, metricIndex,
+ allAtomMatchingTrackers, atomMatchingTrackerMap, allConditionTrackers,
+ conditionTrackerMap, initialConditionCache, wizard, matcherWizard,
+ metricToActivationMap, trackerToMetricMap, conditionToMetricMap,
activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
- metricsWithActivation, eventActivationMap, eventDeactivationMap);
- if (!success) return false;
-
- uint64_t metricHash;
- if (!getMetricProtoHash(config, metric, metric.id(), metricToActivationMap, metricHash)) {
+ metricsWithActivation);
+ if (!producer) {
return false;
}
-
- sp<MetricProducer> gaugeProducer = new GaugeMetricProducer(
- key, metric, conditionIndex, initialConditionCache, wizard, metricHash,
- trackerIndex, matcherWizard, pullTagId, triggerAtomId, atomTagId, timeBaseTimeNs,
- currentTimeNs, pullerManager, eventActivationMap, eventDeactivationMap);
- allMetricProducers.push_back(gaugeProducer);
+ allMetricProducers.push_back(producer.value());
}
for (int i = 0; i < config.no_report_metric_size(); ++i) {
const auto no_report_metric = config.no_report_metric(i);
diff --git a/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h
index f6b2b7d..f909aff 100644
--- a/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h
+++ b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h
@@ -94,8 +94,8 @@
std::unordered_map<int, std::vector<shared_ptr<Activation>>>& newEventDeactivationMap);
// Creates a CountMetricProducer and updates the vectors/maps used by MetricsManager with
-// the appropriate indices. Returns an sp to the producer, or null if there was an error.
-sp<MetricProducer> createCountMetricProducerAndUpdateMetadata(
+// the appropriate indices. Returns an sp to the producer, or nullopt if there was an error.
+optional<sp<MetricProducer>> createCountMetricProducerAndUpdateMetadata(
const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseNs,
const int64_t currentTimeNs, const CountMetric& metric, const int metricIndex,
const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
@@ -113,8 +113,8 @@
std::vector<int>& metricsWithActivation);
// Creates an EventMetricProducer and updates the vectors/maps used by MetricsManager with
-// the appropriate indices. Returns an sp to the producer, or null if there was an error.
-sp<MetricProducer> createEventMetricProducerAndUpdateMetadata(
+// the appropriate indices. Returns an sp to the producer, or nullopt if there was an error.
+optional<sp<MetricProducer>> createEventMetricProducerAndUpdateMetadata(
const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseNs,
const EventMetric& metric, const int metricIndex,
const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
@@ -129,6 +129,25 @@
std::unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
std::vector<int>& metricsWithActivation);
+// Creates a GaugeMetricProducer and updates the vectors/maps used by MetricsManager with
+// the appropriate indices. Returns an sp to the producer, or nullopt if there was an error.
+optional<sp<MetricProducer>> createGaugeMetricProducerAndUpdateMetadata(
+ const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseNs,
+ const int64_t currentTimeNs, const sp<StatsPullerManager>& pullerManager,
+ const GaugeMetric& metric, const int metricIndex,
+ const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
+ const std::unordered_map<int64_t, int>& atomMatchingTrackerMap,
+ std::vector<sp<ConditionTracker>>& allConditionTrackers,
+ const std::unordered_map<int64_t, int>& conditionTrackerMap,
+ const std::vector<ConditionState>& initialConditionCache, const sp<ConditionWizard>& wizard,
+ const sp<EventMatcherWizard>& matcherWizard,
+ const std::unordered_map<int64_t, int>& metricToActivationMap,
+ std::unordered_map<int, std::vector<int>>& trackerToMetricMap,
+ std::unordered_map<int, std::vector<int>>& conditionToMetricMap,
+ std::unordered_map<int, std::vector<int>>& activationAtomTrackerToMetricMap,
+ std::unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
+ std::vector<int>& metricsWithActivation);
+
// Helper functions for MetricsManager to initialize from StatsdConfig.
// *Note*: only initStatsdConfig() should be called from outside.
// All other functions are intermediate
diff --git a/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp b/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp
index 9e675878..60705cf 100644
--- a/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp
+++ b/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp
@@ -27,6 +27,7 @@
#include "src/condition/CombinationConditionTracker.h"
#include "src/condition/SimpleConditionTracker.h"
#include "src/matchers/CombinationAtomMatchingTracker.h"
+#include "src/metrics/GaugeMetricProducer.h"
#include "src/metrics/parsing_utils/metrics_manager_util.h"
#include "tests/statsd_test_util.h"
@@ -137,6 +138,23 @@
return metric;
}
+GaugeMetric createGaugeMetric(string name, int64_t what, GaugeMetric::SamplingType samplingType,
+ optional<int64_t> condition, optional<int64_t> triggerEvent) {
+ GaugeMetric metric;
+ metric.set_id(StringToId(name));
+ metric.set_what(what);
+ metric.set_bucket(TEN_MINUTES);
+ metric.set_sampling_type(samplingType);
+ if (condition) {
+ metric.set_condition(condition.value());
+ }
+ if (triggerEvent) {
+ metric.set_trigger_event(triggerEvent.value());
+ }
+ metric.mutable_gauge_fields_filter()->set_include_all(true);
+ return metric;
+}
+
} // anonymous namespace
TEST_F(ConfigUpdateTest, TestSimpleMatcherPreserve) {
@@ -1266,6 +1284,120 @@
EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE);
}
+TEST_F(ConfigUpdateTest, TestGaugeMetricPreserve) {
+ StatsdConfig config;
+ AtomMatcher startMatcher = CreateScreenTurnedOnAtomMatcher();
+ *config.add_atom_matcher() = startMatcher;
+ AtomMatcher stopMatcher = CreateScreenTurnedOffAtomMatcher();
+ *config.add_atom_matcher() = stopMatcher;
+ AtomMatcher whatMatcher = CreateScreenBrightnessChangedAtomMatcher();
+ *config.add_atom_matcher() = whatMatcher;
+
+ Predicate predicate = CreateScreenIsOnPredicate();
+ *config.add_predicate() = predicate;
+
+ *config.add_gauge_metric() = createGaugeMetric(
+ "GAUGE1", whatMatcher.id(), GaugeMetric::RANDOM_ONE_SAMPLE, predicate.id(), nullopt);
+
+ EXPECT_TRUE(initConfig(config));
+
+ unordered_map<int64_t, int> metricToActivationMap;
+ vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN);
+ EXPECT_TRUE(determineAllMetricUpdateStatuses(config, oldMetricProducerMap, oldMetricProducers,
+ metricToActivationMap,
+ /*replacedMatchers*/ {}, /*replacedConditions=*/{},
+ /*replacedStates=*/{}, metricsToUpdate));
+ EXPECT_EQ(metricsToUpdate[0], UPDATE_PRESERVE);
+}
+
+TEST_F(ConfigUpdateTest, TestGaugeMetricDefinitionChange) {
+ StatsdConfig config;
+ AtomMatcher whatMatcher = CreateScreenBrightnessChangedAtomMatcher();
+ *config.add_atom_matcher() = whatMatcher;
+
+ *config.add_gauge_metric() = createGaugeMetric(
+ "GAUGE1", whatMatcher.id(), GaugeMetric::RANDOM_ONE_SAMPLE, nullopt, nullopt);
+
+ EXPECT_TRUE(initConfig(config));
+
+ // Change split bucket on app upgrade, which should change the proto, causing replacement.
+ config.mutable_gauge_metric(0)->set_split_bucket_for_app_upgrade(false);
+
+ unordered_map<int64_t, int> metricToActivationMap;
+ vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN);
+ EXPECT_TRUE(determineAllMetricUpdateStatuses(config, oldMetricProducerMap, oldMetricProducers,
+ metricToActivationMap,
+ /*replacedMatchers*/ {}, /*replacedConditions=*/{},
+ /*replacedStates=*/{}, metricsToUpdate));
+ EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE);
+}
+
+TEST_F(ConfigUpdateTest, TestGaugeMetricWhatChanged) {
+ StatsdConfig config;
+ AtomMatcher whatMatcher = CreateScreenBrightnessChangedAtomMatcher();
+ *config.add_atom_matcher() = whatMatcher;
+
+ *config.add_gauge_metric() = createGaugeMetric(
+ "GAUGE1", whatMatcher.id(), GaugeMetric::RANDOM_ONE_SAMPLE, nullopt, nullopt);
+
+ EXPECT_TRUE(initConfig(config));
+
+ unordered_map<int64_t, int> metricToActivationMap;
+ vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN);
+ EXPECT_TRUE(determineAllMetricUpdateStatuses(
+ config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
+ /*replacedMatchers*/ {whatMatcher.id()}, /*replacedConditions=*/{},
+ /*replacedStates=*/{}, metricsToUpdate));
+ EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE);
+}
+
+TEST_F(ConfigUpdateTest, TestGaugeMetricConditionChanged) {
+ StatsdConfig config;
+ AtomMatcher startMatcher = CreateScreenTurnedOnAtomMatcher();
+ *config.add_atom_matcher() = startMatcher;
+ AtomMatcher stopMatcher = CreateScreenTurnedOffAtomMatcher();
+ *config.add_atom_matcher() = stopMatcher;
+ AtomMatcher whatMatcher = CreateScreenBrightnessChangedAtomMatcher();
+ *config.add_atom_matcher() = whatMatcher;
+
+ Predicate predicate = CreateScreenIsOnPredicate();
+ *config.add_predicate() = predicate;
+
+ *config.add_gauge_metric() = createGaugeMetric(
+ "GAUGE1", whatMatcher.id(), GaugeMetric::RANDOM_ONE_SAMPLE, predicate.id(), nullopt);
+
+ EXPECT_TRUE(initConfig(config));
+
+ unordered_map<int64_t, int> metricToActivationMap;
+ vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN);
+ EXPECT_TRUE(determineAllMetricUpdateStatuses(
+ config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
+ /*replacedMatchers*/ {}, /*replacedConditions=*/{predicate.id()},
+ /*replacedStates=*/{}, metricsToUpdate));
+ EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE);
+}
+
+TEST_F(ConfigUpdateTest, TestGaugeMetricTriggerEventChanged) {
+ StatsdConfig config;
+ AtomMatcher triggerEvent = CreateScreenTurnedOnAtomMatcher();
+ *config.add_atom_matcher() = triggerEvent;
+ AtomMatcher whatMatcher = CreateTemperatureAtomMatcher();
+ *config.add_atom_matcher() = whatMatcher;
+
+ *config.add_gauge_metric() = createGaugeMetric(
+ "GAUGE1", whatMatcher.id(), GaugeMetric::FIRST_N_SAMPLES, nullopt, triggerEvent.id());
+
+ EXPECT_TRUE(initConfig(config));
+
+ unordered_map<int64_t, int> metricToActivationMap;
+ vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN);
+ EXPECT_TRUE(determineAllMetricUpdateStatuses(
+ config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
+ /*replacedMatchers*/ {triggerEvent.id()}, /*replacedConditions=*/{},
+ /*replacedStates=*/{}, metricsToUpdate));
+ EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE);
+}
+
TEST_F(ConfigUpdateTest, TestUpdateEventMetrics) {
StatsdConfig config;
@@ -1727,6 +1859,221 @@
EXPECT_EQ(screenState.mValue.int_value, android::view::DisplayStateEnum::DISPLAY_STATE_ON);
}
+TEST_F(ConfigUpdateTest, TestUpdateGaugeMetrics) {
+ StatsdConfig config;
+
+ // Add atom matchers/predicates/states. These are mostly needed for initStatsdConfig.
+ AtomMatcher matcher1 = CreateScreenTurnedOnAtomMatcher();
+ int64_t matcher1Id = matcher1.id();
+ *config.add_atom_matcher() = matcher1;
+
+ AtomMatcher matcher2 = CreateScreenTurnedOffAtomMatcher();
+ int64_t matcher2Id = matcher2.id();
+ *config.add_atom_matcher() = matcher2;
+
+ AtomMatcher matcher3 = CreateStartScheduledJobAtomMatcher();
+ int64_t matcher3Id = matcher3.id();
+ *config.add_atom_matcher() = matcher3;
+
+ AtomMatcher matcher4 = CreateTemperatureAtomMatcher();
+ int64_t matcher4Id = matcher4.id();
+ *config.add_atom_matcher() = matcher4;
+
+ AtomMatcher matcher5 = CreateSimpleAtomMatcher("SubsystemSleep", util::SUBSYSTEM_SLEEP_STATE);
+ int64_t matcher5Id = matcher5.id();
+ *config.add_atom_matcher() = matcher5;
+
+ Predicate predicate1 = CreateScreenIsOnPredicate();
+ int64_t predicate1Id = predicate1.id();
+ *config.add_predicate() = predicate1;
+
+ // Add a few gauge metrics.
+ // Will be preserved.
+ GaugeMetric gauge1 = createGaugeMetric("GAUGE1", matcher4Id, GaugeMetric::FIRST_N_SAMPLES,
+ predicate1Id, matcher1Id);
+ int64_t gauge1Id = gauge1.id();
+ *config.add_gauge_metric() = gauge1;
+
+ // Will be replaced.
+ GaugeMetric gauge2 =
+ createGaugeMetric("GAUGE2", matcher1Id, GaugeMetric::FIRST_N_SAMPLES, nullopt, nullopt);
+ int64_t gauge2Id = gauge2.id();
+ *config.add_gauge_metric() = gauge2;
+
+ // Will be replaced.
+ GaugeMetric gauge3 = createGaugeMetric("GAUGE3", matcher5Id, GaugeMetric::FIRST_N_SAMPLES,
+ nullopt, matcher3Id);
+ int64_t gauge3Id = gauge3.id();
+ *config.add_gauge_metric() = gauge3;
+
+ // Will be replaced.
+ GaugeMetric gauge4 = createGaugeMetric("GAUGE4", matcher3Id, GaugeMetric::RANDOM_ONE_SAMPLE,
+ predicate1Id, nullopt);
+ int64_t gauge4Id = gauge4.id();
+ *config.add_gauge_metric() = gauge4;
+
+ // Will be deleted.
+ GaugeMetric gauge5 =
+ createGaugeMetric("GAUGE5", matcher2Id, GaugeMetric::RANDOM_ONE_SAMPLE, nullopt, {});
+ int64_t gauge5Id = gauge5.id();
+ *config.add_gauge_metric() = gauge5;
+
+ EXPECT_TRUE(initConfig(config));
+
+ // Used later to ensure the condition wizard is replaced. Get it before doing the update.
+ sp<EventMatcherWizard> oldMatcherWizard =
+ static_cast<GaugeMetricProducer*>(oldMetricProducers[0].get())->mEventMatcherWizard;
+ EXPECT_EQ(oldMatcherWizard->getStrongCount(), 6);
+
+ // Change gauge2, causing it to be replaced.
+ gauge2.set_max_num_gauge_atoms_per_bucket(50);
+
+ // Mark matcher 3 as replaced. Causes gauge3 and gauge4 to be replaced.
+ set<int64_t> replacedMatchers = {matcher3Id};
+
+ // New gauge metric.
+ GaugeMetric gauge6 = createGaugeMetric("GAUGE6", matcher5Id, GaugeMetric::FIRST_N_SAMPLES,
+ predicate1Id, matcher3Id);
+ int64_t gauge6Id = gauge6.id();
+
+ // Map the matchers and predicates in reverse order to force the indices to change.
+ std::unordered_map<int64_t, int> newAtomMatchingTrackerMap;
+ const int matcher5Index = 0;
+ newAtomMatchingTrackerMap[matcher5Id] = 0;
+ const int matcher4Index = 1;
+ newAtomMatchingTrackerMap[matcher4Id] = 1;
+ const int matcher3Index = 2;
+ newAtomMatchingTrackerMap[matcher3Id] = 2;
+ const int matcher2Index = 3;
+ newAtomMatchingTrackerMap[matcher2Id] = 3;
+ const int matcher1Index = 4;
+ newAtomMatchingTrackerMap[matcher1Id] = 4;
+ // Use the existing matchers. A bit hacky, but saves code and we don't rely on them.
+ vector<sp<AtomMatchingTracker>> newAtomMatchingTrackers(5);
+ std::reverse_copy(oldAtomMatchingTrackers.begin(), oldAtomMatchingTrackers.end(),
+ newAtomMatchingTrackers.begin());
+
+ std::unordered_map<int64_t, int> newConditionTrackerMap;
+ const int predicate1Index = 0;
+ newConditionTrackerMap[predicate1Id] = 0;
+ // Use the existing conditionTrackers. A bit hacky, but saves code and we don't rely on them.
+ vector<sp<ConditionTracker>> newConditionTrackers(1);
+ std::reverse_copy(oldConditionTrackers.begin(), oldConditionTrackers.end(),
+ newConditionTrackers.begin());
+ // Say that predicate1 is unknown since the initial condition never changed.
+ vector<ConditionState> conditionCache = {ConditionState::kUnknown};
+
+ StatsdConfig newConfig;
+ *newConfig.add_gauge_metric() = gauge6;
+ const int gauge6Index = 0;
+ *newConfig.add_gauge_metric() = gauge3;
+ const int gauge3Index = 1;
+ *newConfig.add_gauge_metric() = gauge1;
+ const int gauge1Index = 2;
+ *newConfig.add_gauge_metric() = gauge4;
+ const int gauge4Index = 3;
+ *newConfig.add_gauge_metric() = gauge2;
+ const int gauge2Index = 4;
+
+ // Output data structures to validate.
+ unordered_map<int64_t, int> newMetricProducerMap;
+ vector<sp<MetricProducer>> newMetricProducers;
+ unordered_map<int, vector<int>> conditionToMetricMap;
+ unordered_map<int, vector<int>> trackerToMetricMap;
+ set<int64_t> noReportMetricIds;
+ unordered_map<int, vector<int>> activationAtomTrackerToMetricMap;
+ unordered_map<int, vector<int>> deactivationAtomTrackerToMetricMap;
+ vector<int> metricsWithActivation;
+ EXPECT_TRUE(updateMetrics(
+ key, newConfig, /*timeBaseNs=*/123, /*currentTimeNs=*/12345, new StatsPullerManager(),
+ oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap, replacedMatchers,
+ newAtomMatchingTrackers, newConditionTrackerMap, /*replacedConditions=*/{},
+ newConditionTrackers, conditionCache, /*stateAtomIdMap=*/{}, /*allStateGroupMaps=*/{},
+ /*replacedStates=*/{}, oldMetricProducerMap, oldMetricProducers, newMetricProducerMap,
+ newMetricProducers, conditionToMetricMap, trackerToMetricMap, noReportMetricIds,
+ activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
+ metricsWithActivation));
+
+ unordered_map<int64_t, int> expectedMetricProducerMap = {
+ {gauge1Id, gauge1Index}, {gauge2Id, gauge2Index}, {gauge3Id, gauge3Index},
+ {gauge4Id, gauge4Index}, {gauge6Id, gauge6Index},
+ };
+ EXPECT_THAT(newMetricProducerMap, ContainerEq(expectedMetricProducerMap));
+
+ // Make sure preserved metrics are the same.
+ ASSERT_EQ(newMetricProducers.size(), 5);
+ EXPECT_EQ(oldMetricProducers[oldMetricProducerMap.at(gauge1Id)],
+ newMetricProducers[newMetricProducerMap.at(gauge1Id)]);
+
+ // Make sure replaced metrics are different.
+ EXPECT_NE(oldMetricProducers[oldMetricProducerMap.at(gauge2Id)],
+ newMetricProducers[newMetricProducerMap.at(gauge2Id)]);
+ EXPECT_NE(oldMetricProducers[oldMetricProducerMap.at(gauge3Id)],
+ newMetricProducers[newMetricProducerMap.at(gauge3Id)]);
+ EXPECT_NE(oldMetricProducers[oldMetricProducerMap.at(gauge4Id)],
+ newMetricProducers[newMetricProducerMap.at(gauge4Id)]);
+
+ // Verify the conditionToMetricMap.
+ ASSERT_EQ(conditionToMetricMap.size(), 1);
+ const vector<int>& condition1Metrics = conditionToMetricMap[predicate1Index];
+ EXPECT_THAT(condition1Metrics, UnorderedElementsAre(gauge1Index, gauge4Index, gauge6Index));
+
+ // Verify the trackerToMetricMap.
+ ASSERT_EQ(trackerToMetricMap.size(), 4);
+ const vector<int>& matcher1Metrics = trackerToMetricMap[matcher1Index];
+ EXPECT_THAT(matcher1Metrics, UnorderedElementsAre(gauge1Index, gauge2Index));
+ const vector<int>& matcher3Metrics = trackerToMetricMap[matcher3Index];
+ EXPECT_THAT(matcher3Metrics, UnorderedElementsAre(gauge3Index, gauge4Index, gauge6Index));
+ const vector<int>& matcher4Metrics = trackerToMetricMap[matcher4Index];
+ EXPECT_THAT(matcher4Metrics, UnorderedElementsAre(gauge1Index));
+ const vector<int>& matcher5Metrics = trackerToMetricMap[matcher5Index];
+ EXPECT_THAT(matcher5Metrics, UnorderedElementsAre(gauge3Index, gauge6Index));
+
+ // Verify event activation/deactivation maps.
+ ASSERT_EQ(activationAtomTrackerToMetricMap.size(), 0);
+ ASSERT_EQ(deactivationAtomTrackerToMetricMap.size(), 0);
+ ASSERT_EQ(metricsWithActivation.size(), 0);
+
+ // Verify tracker indices/ids/conditions/states are correct.
+ GaugeMetricProducer* gaugeProducer1 =
+ static_cast<GaugeMetricProducer*>(newMetricProducers[gauge1Index].get());
+ EXPECT_EQ(gaugeProducer1->getMetricId(), gauge1Id);
+ EXPECT_EQ(gaugeProducer1->mConditionTrackerIndex, predicate1Index);
+ EXPECT_EQ(gaugeProducer1->mCondition, ConditionState::kUnknown);
+ EXPECT_EQ(gaugeProducer1->mWhatMatcherIndex, matcher4Index);
+ GaugeMetricProducer* gaugeProducer2 =
+ static_cast<GaugeMetricProducer*>(newMetricProducers[gauge2Index].get());
+ EXPECT_EQ(gaugeProducer2->getMetricId(), gauge2Id);
+ EXPECT_EQ(gaugeProducer2->mConditionTrackerIndex, -1);
+ EXPECT_EQ(gaugeProducer2->mCondition, ConditionState::kTrue);
+ EXPECT_EQ(gaugeProducer2->mWhatMatcherIndex, matcher1Index);
+ GaugeMetricProducer* gaugeProducer3 =
+ static_cast<GaugeMetricProducer*>(newMetricProducers[gauge3Index].get());
+ EXPECT_EQ(gaugeProducer3->getMetricId(), gauge3Id);
+ EXPECT_EQ(gaugeProducer3->mConditionTrackerIndex, -1);
+ EXPECT_EQ(gaugeProducer3->mCondition, ConditionState::kTrue);
+ EXPECT_EQ(gaugeProducer3->mWhatMatcherIndex, matcher5Index);
+ GaugeMetricProducer* gaugeProducer4 =
+ static_cast<GaugeMetricProducer*>(newMetricProducers[gauge4Index].get());
+ EXPECT_EQ(gaugeProducer4->getMetricId(), gauge4Id);
+ EXPECT_EQ(gaugeProducer4->mConditionTrackerIndex, predicate1Index);
+ EXPECT_EQ(gaugeProducer4->mCondition, ConditionState::kUnknown);
+ EXPECT_EQ(gaugeProducer4->mWhatMatcherIndex, matcher3Index);
+ GaugeMetricProducer* gaugeProducer6 =
+ static_cast<GaugeMetricProducer*>(newMetricProducers[gauge6Index].get());
+ EXPECT_EQ(gaugeProducer6->getMetricId(), gauge6Id);
+ EXPECT_EQ(gaugeProducer6->mConditionTrackerIndex, predicate1Index);
+ EXPECT_EQ(gaugeProducer6->mCondition, ConditionState::kUnknown);
+ EXPECT_EQ(gaugeProducer6->mWhatMatcherIndex, matcher5Index);
+
+ sp<EventMatcherWizard> newMatcherWizard = gaugeProducer1->mEventMatcherWizard;
+ EXPECT_NE(newMatcherWizard, oldMatcherWizard);
+ EXPECT_EQ(newMatcherWizard->getStrongCount(), 6);
+ oldMetricProducers.clear();
+ // Only reference to the old wizard should be the one in the test.
+ EXPECT_EQ(oldMatcherWizard->getStrongCount(), 1);
+}
+
TEST_F(ConfigUpdateTest, TestUpdateMetricActivations) {
StatsdConfig config;
// Add atom matchers
@@ -1866,6 +2213,10 @@
int64_t matcher2Id = matcher2.id();
*config.add_atom_matcher() = matcher2;
+ AtomMatcher matcher3 = CreateTemperatureAtomMatcher();
+ int64_t matcher3Id = matcher3.id();
+ *config.add_atom_matcher() = matcher3;
+
Predicate predicate1 = CreateScreenIsOnPredicate();
int64_t predicate1Id = predicate1.id();
*config.add_predicate() = predicate1;
@@ -1881,24 +2232,35 @@
int64_t eventMetricId = eventMetric.id();
*config.add_event_metric() = eventMetric;
+ // Will be replaced because the definition changes - a predicate is added.
+ GaugeMetric gaugeMetric = createGaugeMetric("GAUGE1", matcher3Id,
+ GaugeMetric::RANDOM_ONE_SAMPLE, nullopt, nullopt);
+ int64_t gaugeMetricId = gaugeMetric.id();
+ *config.add_gauge_metric() = gaugeMetric;
+
EXPECT_TRUE(initConfig(config));
// Used later to ensure the condition wizard is replaced. Get it before doing the update.
sp<ConditionWizard> oldConditionWizard = oldMetricProducers[0]->mWizard;
- EXPECT_EQ(oldConditionWizard->getStrongCount(), 3);
+ EXPECT_EQ(oldConditionWizard->getStrongCount(), 4);
// Mark matcher 2 as replaced. Causes eventMetric to be replaced.
set<int64_t> replacedMatchers;
replacedMatchers.insert(matcher2Id);
+ // Add predicate1 as a predicate on gaugeMetric, causing it to be replaced.
+ gaugeMetric.set_condition(predicate1Id);
+
// Map the matchers and predicates in reverse order to force the indices to change.
std::unordered_map<int64_t, int> newAtomMatchingTrackerMap;
- const int matcher2Index = 0;
- newAtomMatchingTrackerMap[matcher2Id] = 0;
- const int matcher1Index = 1;
- newAtomMatchingTrackerMap[matcher1Id] = 1;
+ const int matcher3Index = 0;
+ newAtomMatchingTrackerMap[matcher3Id] = 0;
+ const int matcher2Index = 1;
+ newAtomMatchingTrackerMap[matcher2Id] = 1;
+ const int matcher1Index = 2;
+ newAtomMatchingTrackerMap[matcher1Id] = 2;
// Use the existing matchers. A bit hacky, but saves code and we don't rely on them.
- vector<sp<AtomMatchingTracker>> newAtomMatchingTrackers(2);
+ vector<sp<AtomMatchingTracker>> newAtomMatchingTrackers(3);
std::reverse_copy(oldAtomMatchingTrackers.begin(), oldAtomMatchingTrackers.end(),
newAtomMatchingTrackers.begin());
@@ -1916,6 +2278,8 @@
const int countMetricIndex = 0;
*newConfig.add_event_metric() = eventMetric;
const int eventMetricIndex = 1;
+ *newConfig.add_gauge_metric() = gaugeMetric;
+ const int gaugeMetricIndex = 2;
// Output data structures to validate.
unordered_map<int64_t, int> newMetricProducerMap;
@@ -1939,29 +2303,34 @@
unordered_map<int64_t, int> expectedMetricProducerMap = {
{countMetricId, countMetricIndex},
{eventMetricId, eventMetricIndex},
+ {gaugeMetricId, gaugeMetricIndex},
};
EXPECT_THAT(newMetricProducerMap, ContainerEq(expectedMetricProducerMap));
// Make sure preserved metrics are the same.
- ASSERT_EQ(newMetricProducers.size(), 2);
+ ASSERT_EQ(newMetricProducers.size(), 3);
EXPECT_EQ(oldMetricProducers[oldMetricProducerMap.at(countMetricId)],
newMetricProducers[newMetricProducerMap.at(countMetricId)]);
// Make sure replaced metrics are different.
EXPECT_NE(oldMetricProducers[oldMetricProducerMap.at(eventMetricId)],
newMetricProducers[newMetricProducerMap.at(eventMetricId)]);
+ EXPECT_NE(oldMetricProducers[oldMetricProducerMap.at(gaugeMetricId)],
+ newMetricProducers[newMetricProducerMap.at(gaugeMetricId)]);
// Verify the conditionToMetricMap.
ASSERT_EQ(conditionToMetricMap.size(), 1);
const vector<int>& condition1Metrics = conditionToMetricMap[predicate1Index];
- EXPECT_THAT(condition1Metrics, UnorderedElementsAre(countMetricIndex));
+ EXPECT_THAT(condition1Metrics, UnorderedElementsAre(countMetricIndex, gaugeMetricIndex));
// Verify the trackerToMetricMap.
- ASSERT_EQ(trackerToMetricMap.size(), 2);
+ ASSERT_EQ(trackerToMetricMap.size(), 3);
const vector<int>& matcher1Metrics = trackerToMetricMap[matcher1Index];
EXPECT_THAT(matcher1Metrics, UnorderedElementsAre(countMetricIndex));
const vector<int>& matcher2Metrics = trackerToMetricMap[matcher2Index];
EXPECT_THAT(matcher2Metrics, UnorderedElementsAre(eventMetricIndex));
+ const vector<int>& matcher3Metrics = trackerToMetricMap[matcher3Index];
+ EXPECT_THAT(matcher3Metrics, UnorderedElementsAre(gaugeMetricIndex));
// Verify event activation/deactivation maps.
ASSERT_EQ(activationAtomTrackerToMetricMap.size(), 0);
@@ -1975,10 +2344,13 @@
EXPECT_EQ(newMetricProducers[eventMetricIndex]->getMetricId(), eventMetricId);
EXPECT_EQ(newMetricProducers[eventMetricIndex]->mConditionTrackerIndex, -1);
EXPECT_EQ(newMetricProducers[eventMetricIndex]->mCondition, ConditionState::kTrue);
+ EXPECT_EQ(newMetricProducers[gaugeMetricIndex]->getMetricId(), gaugeMetricId);
+ EXPECT_EQ(newMetricProducers[gaugeMetricIndex]->mConditionTrackerIndex, predicate1Index);
+ EXPECT_EQ(newMetricProducers[gaugeMetricIndex]->mCondition, ConditionState::kUnknown);
sp<ConditionWizard> newConditionWizard = newMetricProducers[0]->mWizard;
EXPECT_NE(newConditionWizard, oldConditionWizard);
- EXPECT_EQ(newConditionWizard->getStrongCount(), 3);
+ EXPECT_EQ(newConditionWizard->getStrongCount(), 4);
oldMetricProducers.clear();
// Only reference to the old wizard should be the one in the test.
EXPECT_EQ(oldConditionWizard->getStrongCount(), 1);
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 1f8cf8a..89cb8b8 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -103,6 +103,11 @@
IBinder whitelistToken, long duration);
/**
+ * Returns the flags set for a {@link PendingIntent}.
+ */
+ public abstract int getPendingIntentFlags(IIntentSender target);
+
+ /**
* Allows a {@link PendingIntent} to start activities from background.
*/
public abstract void setPendingIntentAllowBgActivityStarts(
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 85cb120..3748a33 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -1284,10 +1284,10 @@
}
/**
- * Sets the id of the display where activity should be launched.
- * An app can launch activities on public displays or private displays that are owned by the app
- * or where an app already has activities. Otherwise, trying to launch on a private display
- * or providing an invalid display id will result in an exception.
+ * Sets the id of the display where the activity should be launched.
+ * An app can launch activities on public displays or displays where the app already has
+ * activities. Otherwise, trying to launch on a private display or providing an invalid display
+ * id will result in an exception.
* <p>
* Setting launch display id will be ignored on devices that don't have
* {@link android.content.pm.PackageManager#FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS}.
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index d1fbd76..155de36 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -7337,21 +7337,48 @@
}
/**
- * Make note of an application performing an operation. Note that you must pass
- * in both the uid and name of the application to be checked; this function will verify
- * that these two match, and if not, return {@link #MODE_IGNORED}. If this call
- * succeeds, the last execution time of the operation for this app will be updated to
- * the current time.
+ * Make note of an application performing an operation and check if the application is allowed
+ * to perform it.
*
* <p>If this is a check that is not preceding the protected operation, use
* {@link #unsafeCheckOp} instead.
*
+ * <p>The identity of the package the app-op is noted for is specified by the
+ * {@code uid} and {@code packageName} parameters. If this is noted for a regular app both
+ * should be set and the package needs to be part of the uid. In the very rare case that an
+ * app-op is noted for an entity that does not have a package name, the package can be
+ * {@code null}. As it is possible that a single process contains more than one package the
+ * {@code packageName} should be {@link Context#getPackageName() read} from the context of the
+ * caller of the API (in the app process) that eventually triggers this check. If this op is
+ * not noted for a running process the {@code packageName} cannot be read from the context, but
+ * it should be clear which package the note is for.
+ *
+ * <p>If the {@code uid} and {@code packageName} do not match this return
+ * {@link #MODE_IGNORED}.
+ *
+ * <p>Beside the access check this method also records the access. While the access check is
+ * based on {@code uid} and/or {@code packageName} the access recording is done based on the
+ * {@code packageName} and {@code attributionTag}. The {@code attributionTag} should be
+ * {@link Context#getAttributionTag() read} from the same context the package name is read from.
+ * In the case the check is not related to an API call, the {@code attributionTag} should be
+ * {@code null}. Please note that e.g. registering a callback for later is still an API call and
+ * the code should store the attribution tag along the package name for being used in this
+ * method later.
+ *
+ * <p>The {@code message} parameter only needs to be set when this method is <ul>not</ul>
+ * called in a two-way binder call from the client. In this case the message is a free form text
+ * that is meant help the app developer determine what part of the app's code triggered the
+ * note. This message is passed back to the app in the
+ * {@link OnOpNotedCallback#onAsyncNoted(AsyncNotedAppOp)} callback. A good example of a useful
+ * message is including the {@link System#identityHashCode(Object)} of the listener that will
+ * receive data or the name of the manifest-receiver.
+ *
* @param op The operation to note. One of the OPSTR_* constants.
- * @param uid The user id of the application attempting to perform the operation.
+ * @param uid The uid of the application attempting to perform the operation.
* @param packageName The name of the application attempting to perform the operation.
- * @param attributionTag The {@link Context#createAttributionContext attribution tag} or {@code
- * null} for default attribution
- * @param message A message describing the reason the op was noted
+ * @param attributionTag The {@link Context#createAttributionContext attribution tag} of the
+ * calling context or {@code null} for default attribution
+ * @param message A message describing why the op was noted
*
* @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
* {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
@@ -7359,33 +7386,16 @@
*
* @throws SecurityException If the app has been configured to crash on this op.
*/
+ // For platform callers of this method, please read the package name parameter from
+ // Context#getOpPackageName.
+ // When noting a callback, the message can be computed using the #toReceiverId method.
public int noteOp(@NonNull String op, int uid, @Nullable String packageName,
@Nullable String attributionTag, @Nullable String message) {
return noteOp(strOpToOp(op), uid, packageName, attributionTag, message);
}
/**
- * Make note of an application performing an operation. Note that you must pass
- * in both the uid and name of the application to be checked; this function will verify
- * that these two match, and if not, return {@link #MODE_IGNORED}. If this call
- * succeeds, the last execution time of the operation for this app will be updated to
- * the current time.
- *
- * <p>If this is a check that is not preceding the protected operation, use
- * {@link #unsafeCheckOp} instead.
- *
- * @param op The operation to note. One of the OP_* constants.
- * @param uid The user id of the application attempting to perform the operation.
- * @param packageName The name of the application attempting to perform the operation.
- * @param attributionTag The {@link Context#createAttributionContext attribution tag} or {@code
- * null} for default attribution
- * @param message A message describing the reason the op was noted
- *
- * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
- * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
- * causing the app to crash).
- *
- * @throws SecurityException If the app has been configured to crash on this op.
+ * @see #noteOp(String, int, String, String, String
*
* @hide
*/
@@ -7423,16 +7433,7 @@
* Like {@link #noteOp(String, int, String, String, String)} but instead of throwing a
* {@link SecurityException} it returns {@link #MODE_ERRORED}.
*
- * @param op The operation to note. One of the OPSTR_* constants.
- * @param uid The user id of the application attempting to perform the operation.
- * @param packageName The name of the application attempting to perform the operation.
- * @param attributionTag The {@link Context#createAttributionContext attribution tag} or {@code
- * null} for default attribution
- * @param message A message describing the reason the op was noted
- *
- * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
- * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
- * causing the app to crash).
+ * @see #noteOp(String, int, String, String, String)
*/
public int noteOpNoThrow(@NonNull String op, int uid, @NonNull String packageName,
@Nullable String attributionTag, @Nullable String message) {
@@ -7440,19 +7441,7 @@
}
/**
- * Like {@link #noteOp(String, int, String, String, String)} but instead of throwing a
- * {@link SecurityException} it returns {@link #MODE_ERRORED}.
- *
- * @param op The operation to note. One of the OP_* constants.
- * @param uid The user id of the application attempting to perform the operation.
- * @param packageName The name of the application attempting to perform the operation.
- * @param attributionTag The {@link Context#createAttributionContext attribution tag} or {@code
- * null} for default attribution
- * @param message A message describing the reason the op was noted
- *
- * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
- * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
- * causing the app to crash).
+ * @see #noteOpNoThrow(String, int, String, String, String)
*
* @hide
*/
@@ -7509,23 +7498,7 @@
}
/**
- * Make note of an application performing an operation on behalf of another application when
- * handling an IPC. This function will verify that the calling uid and proxied package name
- * match, and if not, return {@link #MODE_IGNORED}. If this call succeeds, the last execution
- * time of the operation for the proxied app and your app will be updated to the current time.
- *
- * @param op The operation to note. One of the OP_* constants.
- * @param proxiedPackageName The name of the application calling into the proxy application.
- * @param proxiedUid The uid of the proxied application
- * @param proxiedAttributionTag The proxied {@link Context#createAttributionContext
- * attribution tag} or {@code null} for default attribution
- * @param message A message describing the reason the op was noted
- *
- * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or {@link #MODE_IGNORED}
- * if it is not allowed and should be silently ignored (without causing the app to crash).
- *
- * @throws SecurityException If the proxy or proxied app has been configured to crash on this
- * op.
+ * @see #noteProxyOp(String, String, int, String, String)
*
* @hide
*/
@@ -7587,15 +7560,7 @@
* Like {@link #noteProxyOp(String, String, int, String, String)} but instead
* of throwing a {@link SecurityException} it returns {@link #MODE_ERRORED}.
*
- * <p>This API requires package with the {@code proxiedPackageName} to belong to
- * {@code proxiedUid}.
- *
- * @param op The op to note
- * @param proxiedPackageName The package to note the op for
- * @param proxiedUid The uid the package belongs to
- * @param proxiedAttributionTag The proxied {@link Context#createAttributionContext
- * attribution tag} or {@code null} for default attribution
- * @param message A message describing the reason the op was noted
+ * @see #noteOpNoThrow(String, int, String, String, String)
*/
public int noteProxyOpNoThrow(@NonNull String op, @Nullable String proxiedPackageName,
int proxiedUid, @Nullable String proxiedAttributionTag, @Nullable String message) {
@@ -7604,16 +7569,7 @@
}
/**
- * Like {@link #noteProxyOp(int, String, int, String, String)} but instead
- * of throwing a {@link SecurityException} it returns {@link #MODE_ERRORED}.
- *
- * @param op The op to note
- * @param proxiedPackageName The package to note the op for or {@code null} if the op should be
- * noted for the "android" package
- * @param proxiedUid The uid the package belongs to
- * @param proxiedAttributionTag The proxied {@link Context#createAttributionContext
- * attribution tag} or {@code null} for default attribution
- * @param message A message describing the reason the op was noted
+ * @see #noteProxyOpNoThrow(String, String, int, String, String)
*
* @hide
*/
@@ -7701,6 +7657,9 @@
/**
* Like {@link #checkOp} but instead of throwing a {@link SecurityException} it
* returns {@link #MODE_ERRORED}.
+ *
+ * @see #checkOp(int, int, String)
+ *
* @hide
*/
@UnsupportedAppUsage
@@ -7832,6 +7791,10 @@
/**
* Report that an application has started executing a long-running operation.
*
+ * <p>For more details how to determine the {@code callingPackageName},
+ * {@code callingAttributionTag}, and {@code message}, please check the description in
+ * {@link #noteOp(String, int, String, String, String)}
+ *
* @param op The operation to start. One of the OPSTR_* constants.
* @param uid The user id of the application attempting to perform the operation.
* @param packageName The name of the application attempting to perform the operation.
@@ -7852,22 +7815,7 @@
}
/**
- * Report that an application has started executing a long-running operation.
- *
- * @param op The operation to start. One of the OP_* constants.
- * @param uid The user id of the application attempting to perform the operation.
- * @param packageName The name of the application attempting to perform the operation.
- * @param attributionTag The {@link Context#createAttributionContext attribution tag} or
- * {@code null} for default attribution
- * @param startIfModeDefault Whether to start if mode is {@link #MODE_DEFAULT}.
- * @param message Description why op was started
- *
- * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
- * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
- * causing the app to crash).
- *
- * @throws SecurityException If the app has been configured to crash on this op or
- * the package is not in the passed in UID.
+ * @see #startOp(String, int, String, String, String)
*
* @hide
*/
@@ -7913,16 +7861,7 @@
* Like {@link #startOp(String, int, String, String, String)} but instead of throwing a
* {@link SecurityException} it returns {@link #MODE_ERRORED}.
*
- * @param op The operation to start. One of the OP_* constants.
- * @param uid The user id of the application attempting to perform the operation.
- * @param packageName The name of the application attempting to perform the operation.
- * @param attributionTag The {@link Context#createAttributionContext attribution tag} or
- * {@code null} for default attribution
- * @param message Description why op was started
- *
- * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
- * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
- * causing the app to crash).
+ * @see #startOp(String, int, String, String, String)
*/
public int startOpNoThrow(@NonNull String op, int uid, @NonNull String packageName,
@NonNull String attributionTag, @Nullable String message) {
@@ -7930,20 +7869,7 @@
}
/**
- * Like {@link #startOp(int, int, String, boolean, String, String)} but instead of throwing a
- * {@link SecurityException} it returns {@link #MODE_ERRORED}.
- *
- * @param op The operation to start. One of the OP_* constants.
- * @param uid The user id of the application attempting to perform the operation.
- * @param packageName The name of the application attempting to perform the operation.
- * @param attributionTag The {@link Context#createAttributionContext attribution tag} or
- * {@code null} for default attribution
- * @param startIfModeDefault Whether to start if mode is {@link #MODE_DEFAULT}.
- * @param message Description why op was started
- *
- * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
- * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
- * causing the app to crash).
+ * @see #startOpNoThrow(String, int, String, String, String)
*
* @hide
*/
@@ -8102,10 +8028,7 @@
}
/**
- * Report that an application is no longer performing an operation that had previously
- * been started with {@link #startOp(int, int, String, boolean, String, String)}. There is no
- * validation of input or result; the parameters supplied here must be the exact same ones
- * previously passed in when starting the operation.
+ * @see #finishOp(String, int, String, String)
*
* @hide
*/
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 9100d57..90401ad 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -107,6 +107,8 @@
import android.media.MediaTranscodeManager;
import android.media.midi.IMidiManager;
import android.media.midi.MidiManager;
+import android.media.musicrecognition.IMusicRecognitionManager;
+import android.media.musicrecognition.MusicRecognitionManager;
import android.media.projection.MediaProjectionManager;
import android.media.soundtrigger.SoundTriggerManager;
import android.media.tv.ITvInputManager;
@@ -1119,6 +1121,17 @@
return new AutofillManager(ctx.getOuterContext(), service);
}});
+ registerService(Context.MUSIC_RECOGNITION_SERVICE, MusicRecognitionManager.class,
+ new CachedServiceFetcher<MusicRecognitionManager>() {
+ @Override
+ public MusicRecognitionManager createService(ContextImpl ctx) {
+ IBinder b = ServiceManager.getService(
+ Context.MUSIC_RECOGNITION_SERVICE);
+ return new MusicRecognitionManager(
+ IMusicRecognitionManager.Stub.asInterface(b));
+ }
+ });
+
registerService(Context.CONTENT_CAPTURE_MANAGER_SERVICE, ContentCaptureManager.class,
new CachedServiceFetcher<ContentCaptureManager>() {
@Override
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 8a85b79..b74e18b 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -5718,8 +5718,8 @@
* System apps can always bypass VPN.
* <p> Note that the system doesn't update the allowlist when packages are installed or
* uninstalled, the admin app must call this method to keep the list up to date.
- * <p> When {@code lockdownEnabled} is false {@code lockdownWhitelist} is ignored . When
- * {@code lockdownEnabled} is {@code true} and {@code lockdownWhitelist} is {@code null} or
+ * <p> When {@code lockdownEnabled} is false {@code lockdownAllowlist} is ignored . When
+ * {@code lockdownEnabled} is {@code true} and {@code lockdownAllowlist} is {@code null} or
* empty, only system apps can bypass VPN.
* <p> Setting always-on VPN package to {@code null} or using
* {@link #setAlwaysOnVpnPackage(ComponentName, String, boolean)} clears lockdown allowlist.
@@ -5728,24 +5728,24 @@
* to remove an existing always-on VPN configuration
* @param lockdownEnabled {@code true} to disallow networking when the VPN is not connected or
* {@code false} otherwise. This has no effect when clearing.
- * @param lockdownWhitelist Packages that will be able to access the network directly when VPN
+ * @param lockdownAllowlist Packages that will be able to access the network directly when VPN
* is in lockdown mode but not connected. Has no effect when clearing.
* @throws SecurityException if {@code admin} is not a device or a profile
* owner.
* @throws NameNotFoundException if {@code vpnPackage} or one of
- * {@code lockdownWhitelist} is not installed.
+ * {@code lockdownAllowlist} is not installed.
* @throws UnsupportedOperationException if {@code vpnPackage} exists but does
* not support being set as always-on, or if always-on VPN is not
* available.
*/
public void setAlwaysOnVpnPackage(@NonNull ComponentName admin, @Nullable String vpnPackage,
- boolean lockdownEnabled, @Nullable Set<String> lockdownWhitelist)
+ boolean lockdownEnabled, @Nullable Set<String> lockdownAllowlist)
throws NameNotFoundException {
throwIfParentInstance("setAlwaysOnVpnPackage");
if (mService != null) {
try {
mService.setAlwaysOnVpnPackage(admin, vpnPackage, lockdownEnabled,
- lockdownWhitelist == null ? null : new ArrayList<>(lockdownWhitelist));
+ lockdownAllowlist == null ? null : new ArrayList<>(lockdownAllowlist));
} catch (ServiceSpecificException e) {
switch (e.errorCode) {
case ERROR_VPN_PACKAGE_NOT_FOUND:
@@ -5820,9 +5820,9 @@
throwIfParentInstance("getAlwaysOnVpnLockdownWhitelist");
if (mService != null) {
try {
- final List<String> whitelist =
- mService.getAlwaysOnVpnLockdownWhitelist(admin);
- return whitelist == null ? null : new HashSet<>(whitelist);
+ final List<String> allowlist =
+ mService.getAlwaysOnVpnLockdownAllowlist(admin);
+ return allowlist == null ? null : new HashSet<>(allowlist);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/app/admin/FreezePeriod.java b/core/java/android/app/admin/FreezePeriod.java
index 657f017..eb6efec 100644
--- a/core/java/android/app/admin/FreezePeriod.java
+++ b/core/java/android/app/admin/FreezePeriod.java
@@ -39,8 +39,8 @@
public class FreezePeriod {
private static final String TAG = "FreezePeriod";
- private static final int DUMMY_YEAR = 2001;
- static final int DAYS_IN_YEAR = 365; // 365 since DUMMY_YEAR is not a leap year
+ private static final int SENTINEL_YEAR = 2001;
+ static final int DAYS_IN_YEAR = 365; // 365 since SENTINEL_YEAR is not a leap year
private final MonthDay mStart;
private final MonthDay mEnd;
@@ -60,9 +60,9 @@
*/
public FreezePeriod(MonthDay start, MonthDay end) {
mStart = start;
- mStartDay = mStart.atYear(DUMMY_YEAR).getDayOfYear();
+ mStartDay = mStart.atYear(SENTINEL_YEAR).getDayOfYear();
mEnd = end;
- mEndDay = mEnd.atYear(DUMMY_YEAR).getDayOfYear();
+ mEndDay = mEnd.atYear(SENTINEL_YEAR).getDayOfYear();
}
/**
@@ -166,9 +166,9 @@
endYearAdjustment = 1;
}
}
- final LocalDate startDate = LocalDate.ofYearDay(DUMMY_YEAR, mStartDay).withYear(
+ final LocalDate startDate = LocalDate.ofYearDay(SENTINEL_YEAR, mStartDay).withYear(
now.getYear() + startYearAdjustment);
- final LocalDate endDate = LocalDate.ofYearDay(DUMMY_YEAR, mEndDay).withYear(
+ final LocalDate endDate = LocalDate.ofYearDay(SENTINEL_YEAR, mEndDay).withYear(
now.getYear() + endYearAdjustment);
return new Pair<>(startDate, endDate);
}
@@ -176,13 +176,13 @@
@Override
public String toString() {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMM dd");
- return LocalDate.ofYearDay(DUMMY_YEAR, mStartDay).format(formatter) + " - "
- + LocalDate.ofYearDay(DUMMY_YEAR, mEndDay).format(formatter);
+ return LocalDate.ofYearDay(SENTINEL_YEAR, mStartDay).format(formatter) + " - "
+ + LocalDate.ofYearDay(SENTINEL_YEAR, mEndDay).format(formatter);
}
/** @hide */
private static MonthDay dayOfYearToMonthDay(int dayOfYear) {
- LocalDate date = LocalDate.ofYearDay(DUMMY_YEAR, dayOfYear);
+ LocalDate date = LocalDate.ofYearDay(SENTINEL_YEAR, dayOfYear);
return MonthDay.of(date.getMonth(), date.getDayOfMonth());
}
@@ -191,7 +191,7 @@
* @hide
*/
private static int dayOfYearDisregardLeapYear(LocalDate date) {
- return date.withYear(DUMMY_YEAR).getDayOfYear();
+ return date.withYear(SENTINEL_YEAR).getDayOfYear();
}
/**
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 1c7b617..60dce22 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -197,12 +197,12 @@
void setCertInstallerPackage(in ComponentName who, String installerPackage);
String getCertInstallerPackage(in ComponentName who);
- boolean setAlwaysOnVpnPackage(in ComponentName who, String vpnPackage, boolean lockdown, in List<String> lockdownWhitelist);
+ boolean setAlwaysOnVpnPackage(in ComponentName who, String vpnPackage, boolean lockdown, in List<String> lockdownAllowlist);
String getAlwaysOnVpnPackage(in ComponentName who);
String getAlwaysOnVpnPackageForUser(int userHandle);
boolean isAlwaysOnVpnLockdownEnabled(in ComponentName who);
boolean isAlwaysOnVpnLockdownEnabledForUser(int userHandle);
- List<String> getAlwaysOnVpnLockdownWhitelist(in ComponentName who);
+ List<String> getAlwaysOnVpnLockdownAllowlist(in ComponentName who);
void addPersistentPreferredActivity(in ComponentName admin, in IntentFilter filter, in ComponentName activity);
void clearPackagePersistentPreferredActivities(in ComponentName admin, String packageName);
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 666ba32..9c216a3 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -4502,6 +4502,14 @@
public static final String SOUND_TRIGGER_MIDDLEWARE_SERVICE = "soundtrigger_middleware";
/**
+ * Used to access {@link MusicRecognitionManagerService}.
+ *
+ * @hide
+ * @see #getSystemService(String)
+ */
+ public static final String MUSIC_RECOGNITION_SERVICE = "music_recognition";
+
+ /**
* Official published name of the (internal) permission service.
*
* @see #getSystemService(String)
diff --git a/core/java/android/content/PermissionChecker.java b/core/java/android/content/PermissionChecker.java
index eec7c9c..159db92 100644
--- a/core/java/android/content/PermissionChecker.java
+++ b/core/java/android/content/PermissionChecker.java
@@ -116,6 +116,10 @@
* will evaluate the permission access based on the current fg/bg state of the app and
* leave a record that the data was accessed.
*
+ * <p>For more details how to determine the {@code packageName}, {@code attributionTag}, and
+ * {@code message}, please check the description in
+ * {@link AppOpsManager#noteOp(String, int, String, String, String)}
+ *
* @param context Context for accessing resources.
* @param permission The permission to check.
* @param pid The process id for which to check. Use {@link #PID_UNKNOWN} if the PID
@@ -262,11 +266,15 @@
* will evaluate the permission access based on the current fg/bg state of the app and
* leave a record that the data was accessed.
*
+ * <p>For more details how to determine the {@code callingPackageName},
+ * {@code callingAttributionTag}, and {@code message}, please check the description in
+ * {@link AppOpsManager#noteOp(String, int, String, String, String)}
+ *
* @param context Context for accessing resources.
* @param permission The permission to check.
- * @param packageName The package name making the IPC. If null the
+ * @param callingPackageName The package name making the IPC. If null the
* the first package for the calling UID will be used.
- * @param attributionTag attribution tag
+ * @param callingAttributionTag attribution tag
* @return The permission check result which is either {@link #PERMISSION_GRANTED}
* or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
* @param message A message describing the reason the permission was checked
@@ -275,13 +283,13 @@
*/
@PermissionResult
public static int checkCallingPermissionForDataDelivery(@NonNull Context context,
- @NonNull String permission, @Nullable String packageName,
- @Nullable String attributionTag, @Nullable String message) {
+ @NonNull String permission, @Nullable String callingPackageName,
+ @Nullable String callingAttributionTag, @Nullable String message) {
if (Binder.getCallingPid() == Process.myPid()) {
return PERMISSION_HARD_DENIED;
}
return checkPermissionForDataDelivery(context, permission, Binder.getCallingPid(),
- Binder.getCallingUid(), packageName, attributionTag, message);
+ Binder.getCallingUid(), callingPackageName, callingAttributionTag, message);
}
/**
@@ -339,6 +347,10 @@
* will evaluate the permission access based on the current fg/bg state of the app and
* leave a record that the data was accessed.
*
+ * <p>For more details how to determine the {@code callingPackageName},
+ * {@code callingAttributionTag}, and {@code message}, please check the description in
+ * {@link AppOpsManager#noteOp(String, int, String, String, String)}
+ *
* @param context Context for accessing resources.
* @param permission The permission to check.
* @return The permission check result which is either {@link #PERMISSION_GRANTED}
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 79e3eea..30f3325c 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -379,8 +379,7 @@
/**
* Logs process start information (including APK hash) to the security log.
*/
- void logAppProcessStartIfNeeded(String processName, int uid, String seinfo, String apkFile,
- int pid);
+ void logAppProcessStartIfNeeded(String packageName, String processName, int uid, String seinfo, String apkFile, int pid);
/**
* As per {@link android.content.pm.PackageManager#flushPackageRestrictionsAsUser}.
diff --git a/core/java/android/hardware/biometrics/BiometricManager.java b/core/java/android/hardware/biometrics/BiometricManager.java
index 8d0cc68..35ef53b 100644
--- a/core/java/android/hardware/biometrics/BiometricManager.java
+++ b/core/java/android/hardware/biometrics/BiometricManager.java
@@ -16,14 +16,17 @@
package android.hardware.biometrics;
+import static android.Manifest.permission.TEST_BIOMETRIC;
import static android.Manifest.permission.USE_BIOMETRIC;
import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL;
import static android.Manifest.permission.WRITE_DEVICE_CONFIG;
import android.annotation.IntDef;
+import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
+import android.annotation.TestApi;
import android.content.Context;
import android.os.RemoteException;
import android.security.keystore.KeyGenParameterSpec;
@@ -196,6 +199,17 @@
}
/**
+ * Retrieves a test session for BiometricManager/BiometricPrompt.
+ * @hide
+ */
+ @TestApi
+ @NonNull
+ @RequiresPermission(TEST_BIOMETRIC)
+ public BiometricTestSession getTestSession() {
+ return null; // TODO(169459906)
+ }
+
+ /**
* Determine if biometrics can be used. In other words, determine if
* {@link BiometricPrompt} can be expected to be shown (hardware available, templates enrolled,
* user-enabled). This is the equivalent of {@link #canAuthenticate(int)} with
diff --git a/core/java/android/hardware/biometrics/BiometricTestSession.java b/core/java/android/hardware/biometrics/BiometricTestSession.java
new file mode 100644
index 0000000..719efa8c
--- /dev/null
+++ b/core/java/android/hardware/biometrics/BiometricTestSession.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.biometrics;
+
+import static android.Manifest.permission.TEST_BIOMETRIC;
+
+import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
+import android.annotation.TestApi;
+import android.content.Context;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Common set of interfaces to test biometric-related APIs, including {@link BiometricPrompt} and
+ * {@link android.hardware.fingerprint.FingerprintManager}.
+ * @hide
+ */
+@TestApi
+public class BiometricTestSession implements AutoCloseable {
+
+ private static final String TAG = "TestManager";
+
+ private final Context mContext;
+ private final ITestService mTestService;
+
+ /**
+ * @hide
+ */
+ public BiometricTestSession(@NonNull Context context, @NonNull ITestService testService) {
+ mContext = context;
+ mTestService = testService;
+ }
+
+ /**
+ * @return A list of {@link SensorProperties}
+ */
+ @NonNull
+ @RequiresPermission(TEST_BIOMETRIC)
+ public List<SensorProperties> getSensorProperties() {
+ try {
+ final List<SensorPropertiesInternal> internalProps =
+ mTestService.getSensorPropertiesInternal(mContext.getOpPackageName());
+ final List<SensorProperties> props = new ArrayList<>();
+ for (SensorPropertiesInternal internalProp : internalProps) {
+ props.add(new SensorProperties(internalProp.sensorId, internalProp.sensorStrength));
+ }
+ return props;
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Switches the specified sensor to use a test HAL. In this mode, the framework will not invoke
+ * any methods on the real HAL implementation. This allows the framework to test a substantial
+ * portion of the framework code that would otherwise require human interaction. Note that
+ * secure pathways such as HAT/Keystore are not testable, since they depend on the TEE or its
+ * equivalent for the secret key.
+ *
+ * @param sensorId Sensor that this command applies to.
+ * @param enableTestHal If true, enable testing with a fake HAL instead of the real HAL.
+ */
+ @RequiresPermission(TEST_BIOMETRIC)
+ public void enableTestHal(int sensorId, boolean enableTestHal) {
+ try {
+ mTestService.enableTestHal(sensorId, enableTestHal);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Remote exception", e);
+ }
+ }
+
+ /**
+ * Starts the enrollment process. This should generally be used when the test HAL is enabled.
+ *
+ * @param sensorId Sensor that this command applies to.
+ * @param userId User that this command applies to.
+ */
+ @RequiresPermission(TEST_BIOMETRIC)
+ public void enrollStart(int sensorId, int userId) {
+ try {
+ mTestService.enrollStart(sensorId, userId);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Remote exception", e);
+ }
+ }
+
+ /**
+ * Finishes the enrollment process. Simulates the HAL's callback.
+ *
+ * @param sensorId Sensor that this command applies to.
+ * @param userId User that this command applies to.
+ */
+ @RequiresPermission(TEST_BIOMETRIC)
+ public void enrollFinish(int sensorId, int userId) {
+ try {
+ mTestService.enrollFinish(sensorId, userId);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Remote exception", e);
+ }
+ }
+
+ /**
+ * Simulates a successful authentication, but does not provide a valid HAT.
+ *
+ * @param sensorId Sensor that this command applies to.
+ * @param userId User that this command applies to.
+ */
+ @RequiresPermission(TEST_BIOMETRIC)
+ public void authenticateSuccess(int sensorId, int userId) {
+ try {
+ mTestService.authenticateSuccess(sensorId, userId);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Remote exception", e);
+ }
+ }
+
+ /**
+ * Simulates a rejected attempt.
+ *
+ * @param sensorId Sensor that this command applies to.
+ * @param userId User that this command applies to.
+ */
+ @RequiresPermission(TEST_BIOMETRIC)
+ public void authenticateReject(int sensorId, int userId) {
+ try {
+ mTestService.authenticateReject(sensorId, userId);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Remote exception", e);
+ }
+ }
+
+ /**
+ * Simulates an acquired message from the HAL.
+ *
+ * @param sensorId Sensor that this command applies to.
+ * @param userId User that this command applies to.
+ */
+ @RequiresPermission(TEST_BIOMETRIC)
+ public void notifyAcquired(int sensorId, int userId) {
+ try {
+ mTestService.notifyAcquired(sensorId, userId);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Remote exception", e);
+ }
+ }
+
+ /**
+ * Simulates an error message from the HAL.
+ *
+ * @param sensorId Sensor that this command applies to.
+ * @param userId User that this command applies to.
+ */
+ @RequiresPermission(TEST_BIOMETRIC)
+ public void notifyError(int sensorId, int userId) {
+ try {
+ mTestService.notifyError(sensorId, userId);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Remote exception", e);
+ }
+ }
+
+ /**
+ * Matches the framework's cached enrollments against the HAL's enrollments. Any enrollment
+ * that isn't known by both sides are deleted. This should generally be used when the test
+ * HAL is disabled (e.g. to clean up after a test).
+ *
+ * @param sensorId Sensor that this command applies to.
+ * @param userId User that this command applies to.
+ */
+ @RequiresPermission(TEST_BIOMETRIC)
+ public void internalCleanup(int sensorId, int userId) {
+ try {
+ mTestService.internalCleanup(sensorId, userId);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Remote exception", e);
+ }
+ }
+
+ @Override
+ @RequiresPermission(TEST_BIOMETRIC)
+ public void close() {
+
+ }
+}
diff --git a/core/java/android/hardware/biometrics/ITestService.aidl b/core/java/android/hardware/biometrics/ITestService.aidl
new file mode 100644
index 0000000..6373132
--- /dev/null
+++ b/core/java/android/hardware/biometrics/ITestService.aidl
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.biometrics;
+
+import android.hardware.biometrics.SensorPropertiesInternal;
+
+/**
+ * A test service for FingerprintManager and BiometricPrompt.
+ * @hide
+ */
+interface ITestService {
+ // Returns a list of sensor properties supported by the interface.
+ List<SensorPropertiesInternal> getSensorPropertiesInternal(String opPackageName);
+
+ // Switches the specified sensor to use a test HAL. In this mode, the framework will not invoke
+ // any methods on the real HAL implementation. This allows the framework to test a substantial
+ // portion of the framework code that would otherwise require human interaction. Note that
+ // secure pathways such as HAT/Keystore are not testable, since they depend on the TEE or its
+ // equivalent for the secret key.
+ void enableTestHal(int sensorId, boolean enableTestHal);
+
+ // Starts the enrollment process. This should generally be used when the test HAL is enabled.
+ void enrollStart(int sensorId, int userId);
+
+ // Finishes the enrollment process. Simulates the HAL's callback.
+ void enrollFinish(int sensorId, int userId);
+
+ // Simulates a successful authentication, but does not provide a valid HAT.
+ void authenticateSuccess(int sensorId, int userId);
+
+ // Simulates a rejected attempt.
+ void authenticateReject(int sensorId, int userId);
+
+ // Simulates an acquired message from the HAL.
+ void notifyAcquired(int sensorId, int userId);
+
+ // Simulates an error message from the HAL.
+ void notifyError(int sensorId, int userId);
+
+ // Matches the framework's cached enrollments against the HAL's enrollments. Any enrollment
+ // that isn't known by both sides are deleted. This should generally be used when the test
+ // HAL is disabled (e.g. to clean up after a test).
+ void internalCleanup(int sensorId, int userId);
+}
diff --git a/core/java/android/hardware/biometrics/SensorProperties.java b/core/java/android/hardware/biometrics/SensorProperties.java
index b3dcb8f..5b1b5e6 100644
--- a/core/java/android/hardware/biometrics/SensorProperties.java
+++ b/core/java/android/hardware/biometrics/SensorProperties.java
@@ -17,6 +17,7 @@
package android.hardware.biometrics;
import android.annotation.IntDef;
+import android.annotation.TestApi;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -25,19 +26,18 @@
* The base class containing all modality-agnostic information.
* @hide
*/
+@TestApi
public class SensorProperties {
/**
* A sensor that meets the requirements for Class 1 biometrics as defined in the CDD. This does
* not correspond to a public BiometricManager.Authenticators constant. Sensors of this strength
* are not available to applications via the public API surface.
- * @hide
*/
public static final int STRENGTH_CONVENIENCE = 0;
/**
* A sensor that meets the requirements for Class 2 biometrics as defined in the CDD.
* Corresponds to BiometricManager.Authenticators.BIOMETRIC_WEAK.
- * @hide
*/
public static final int STRENGTH_WEAK = 1;
@@ -46,7 +46,6 @@
* Corresponds to BiometricManager.Authenticators.BIOMETRIC_STRONG.
*
* Notably, this is the only strength that allows generation of HardwareAuthToken(s).
- * @hide
*/
public static final int STRENGTH_STRONG = 2;
@@ -70,7 +69,6 @@
/**
* @return The sensor's unique identifier.
- * @hide
*/
public int getSensorId() {
return mSensorId;
@@ -78,7 +76,6 @@
/**
* @return The sensor's strength.
- * @hide
*/
@Strength
public int getSensorStrength() {
diff --git a/media/java/android/media/tv/TvChannelInfo.aidl b/core/java/android/hardware/biometrics/SensorPropertiesInternal.aidl
similarity index 80%
copy from media/java/android/media/tv/TvChannelInfo.aidl
copy to core/java/android/hardware/biometrics/SensorPropertiesInternal.aidl
index 71cd0a7..d85c788 100644
--- a/media/java/android/media/tv/TvChannelInfo.aidl
+++ b/core/java/android/hardware/biometrics/SensorPropertiesInternal.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 The Android Open Source Project
+ * Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package android.hardware.biometrics;
-package android.media.tv;
-
-parcelable TvChannelInfo;
+parcelable SensorPropertiesInternal;
\ No newline at end of file
diff --git a/core/java/android/hardware/fingerprint/Fingerprint.java b/core/java/android/hardware/fingerprint/Fingerprint.java
index 57e52d9..9ce834ca 100644
--- a/core/java/android/hardware/fingerprint/Fingerprint.java
+++ b/core/java/android/hardware/fingerprint/Fingerprint.java
@@ -31,6 +31,10 @@
mGroupId = groupId;
}
+ public Fingerprint(CharSequence name, int fingerId, long deviceId) {
+ super(name, fingerId, deviceId);
+ }
+
private Fingerprint(Parcel in) {
super(in.readString(), in.readInt(), in.readLong());
mGroupId = in.readInt();
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index 23de303..84c5ea5 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -19,6 +19,7 @@
import static android.Manifest.permission.INTERACT_ACROSS_USERS;
import static android.Manifest.permission.MANAGE_FINGERPRINT;
import static android.Manifest.permission.RESET_FINGERPRINT_LOCKOUT;
+import static android.Manifest.permission.TEST_BIOMETRIC;
import static android.Manifest.permission.USE_BIOMETRIC;
import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL;
import static android.Manifest.permission.USE_FINGERPRINT;
@@ -28,6 +29,7 @@
import android.annotation.RequiresFeature;
import android.annotation.RequiresPermission;
import android.annotation.SystemService;
+import android.annotation.TestApi;
import android.app.ActivityManager;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
@@ -35,6 +37,7 @@
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricFingerprintConstants;
import android.hardware.biometrics.BiometricPrompt;
+import android.hardware.biometrics.BiometricTestSession;
import android.hardware.biometrics.IBiometricServiceLockoutResetCallback;
import android.os.Binder;
import android.os.CancellationSignal;
@@ -94,6 +97,22 @@
private Fingerprint mRemovalFingerprint;
private Handler mHandler;
+ /**
+ * Retrieves a test session for FingerprintManager.
+ * @hide
+ */
+ @TestApi
+ @NonNull
+ @RequiresPermission(TEST_BIOMETRIC)
+ public BiometricTestSession getTestSession() {
+ try {
+ return new BiometricTestSession(mContext,
+ mService.getTestService(mContext.getOpPackageName()));
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
private class OnEnrollCancelListener implements OnCancelListener {
@Override
public void onCancel() {
@@ -761,14 +780,14 @@
* @hide
*/
@RequiresPermission(USE_BIOMETRIC_INTERNAL)
- public void onFingerDown(int sensorId, int x, int y, float minor, float major) {
+ public void onPointerDown(int sensorId, int x, int y, float minor, float major) {
if (mService == null) {
Slog.w(TAG, "onFingerDown: no fingerprint service");
return;
}
try {
- mService.onFingerDown(sensorId, x, y, minor, major);
+ mService.onPointerDown(sensorId, x, y, minor, major);
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
@@ -778,14 +797,14 @@
* @hide
*/
@RequiresPermission(USE_BIOMETRIC_INTERNAL)
- public void onFingerUp(int sensorId) {
+ public void onPointerUp(int sensorId) {
if (mService == null) {
Slog.w(TAG, "onFingerDown: no fingerprint service");
return;
}
try {
- mService.onFingerUp(sensorId);
+ mService.onPointerUp(sensorId);
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
diff --git a/core/java/android/hardware/fingerprint/FingerprintSensorPropertiesInternal.java b/core/java/android/hardware/fingerprint/FingerprintSensorPropertiesInternal.java
index d5ce9e3..1f896cd 100644
--- a/core/java/android/hardware/fingerprint/FingerprintSensorPropertiesInternal.java
+++ b/core/java/android/hardware/fingerprint/FingerprintSensorPropertiesInternal.java
@@ -85,4 +85,9 @@
return false;
}
}
+
+ @Override
+ public String toString() {
+ return "ID: " + sensorId + ", Strength: " + sensorStrength + ", Type: " + sensorType;
+ }
}
diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
index 7af7380..518e3ca 100644
--- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl
+++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
@@ -17,6 +17,7 @@
import android.hardware.biometrics.IBiometricSensorReceiver;
import android.hardware.biometrics.IBiometricServiceLockoutResetCallback;
+import android.hardware.biometrics.ITestService;
import android.hardware.fingerprint.IFingerprintClientActiveCallback;
import android.hardware.fingerprint.IFingerprintServiceReceiver;
import android.hardware.fingerprint.IUdfpsOverlayController;
@@ -30,6 +31,10 @@
* @hide
*/
interface IFingerprintService {
+
+ // Retrieves a test service
+ ITestService getTestService(String opPackageName);
+
// Retrieve static sensor properties for all fingerprint sensors
List<FingerprintSensorPropertiesInternal> getSensorPropertiesInternal(String opPackageName);
@@ -121,10 +126,10 @@
void initializeConfiguration(int sensorId, int strength);
// Notifies about a finger touching the sensor area.
- void onFingerDown(int sensorId, int x, int y, float minor, float major);
+ void onPointerDown(int sensorId, int x, int y, float minor, float major);
// Notifies about a finger leaving the sensor area.
- void onFingerUp(int sensorId);
+ void onPointerUp(int sensorId);
// Sets the controller for managing the UDFPS overlay.
void setUdfpsOverlayController(in IUdfpsOverlayController controller);
diff --git a/core/java/android/net/KeepalivePacketData.java b/core/java/android/net/KeepalivePacketData.java
index e21cb44..5877f1f 100644
--- a/core/java/android/net/KeepalivePacketData.java
+++ b/core/java/android/net/KeepalivePacketData.java
@@ -22,9 +22,10 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.net.util.IpUtils;
import android.util.Log;
+import com.android.net.module.util.IpUtils;
+
import java.net.InetAddress;
/**
diff --git a/core/java/android/net/NattKeepalivePacketData.java b/core/java/android/net/NattKeepalivePacketData.java
index 22288b6..c4f8fc2 100644
--- a/core/java/android/net/NattKeepalivePacketData.java
+++ b/core/java/android/net/NattKeepalivePacketData.java
@@ -22,11 +22,12 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.net.util.IpUtils;
import android.os.Parcel;
import android.os.Parcelable;
import android.system.OsConstants;
+import com.android.net.module.util.IpUtils;
+
import java.net.Inet4Address;
import java.net.InetAddress;
import java.nio.ByteBuffer;
diff --git a/core/java/android/net/util/IpUtils.java b/core/java/android/net/util/IpUtils.java
deleted file mode 100644
index e037c40..0000000
--- a/core/java/android/net/util/IpUtils.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.util;
-
-import java.net.Inet6Address;
-import java.net.InetAddress;
-import java.nio.BufferOverflowException;
-import java.nio.BufferUnderflowException;
-import java.nio.ByteBuffer;
-import java.nio.ShortBuffer;
-
-import static android.system.OsConstants.IPPROTO_TCP;
-import static android.system.OsConstants.IPPROTO_UDP;
-
-/**
- * @hide
- */
-public class IpUtils {
- /**
- * Converts a signed short value to an unsigned int value. Needed
- * because Java does not have unsigned types.
- */
- private static int intAbs(short v) {
- return v & 0xFFFF;
- }
-
- /**
- * Performs an IP checksum (used in IP header and across UDP
- * payload) on the specified portion of a ByteBuffer. The seed
- * allows the checksum to commence with a specified value.
- */
- private static int checksum(ByteBuffer buf, int seed, int start, int end) {
- int sum = seed;
- final int bufPosition = buf.position();
-
- // set position of original ByteBuffer, so that the ShortBuffer
- // will be correctly initialized
- buf.position(start);
- ShortBuffer shortBuf = buf.asShortBuffer();
-
- // re-set ByteBuffer position
- buf.position(bufPosition);
-
- final int numShorts = (end - start) / 2;
- for (int i = 0; i < numShorts; i++) {
- sum += intAbs(shortBuf.get(i));
- }
- start += numShorts * 2;
-
- // see if a singleton byte remains
- if (end != start) {
- short b = buf.get(start);
-
- // make it unsigned
- if (b < 0) {
- b += 256;
- }
-
- sum += b * 256;
- }
-
- sum = ((sum >> 16) & 0xFFFF) + (sum & 0xFFFF);
- sum = ((sum + ((sum >> 16) & 0xFFFF)) & 0xFFFF);
- int negated = ~sum;
- return intAbs((short) negated);
- }
-
- private static int pseudoChecksumIPv4(
- ByteBuffer buf, int headerOffset, int protocol, int transportLen) {
- int partial = protocol + transportLen;
- partial += intAbs(buf.getShort(headerOffset + 12));
- partial += intAbs(buf.getShort(headerOffset + 14));
- partial += intAbs(buf.getShort(headerOffset + 16));
- partial += intAbs(buf.getShort(headerOffset + 18));
- return partial;
- }
-
- private static int pseudoChecksumIPv6(
- ByteBuffer buf, int headerOffset, int protocol, int transportLen) {
- int partial = protocol + transportLen;
- for (int offset = 8; offset < 40; offset += 2) {
- partial += intAbs(buf.getShort(headerOffset + offset));
- }
- return partial;
- }
-
- private static byte ipversion(ByteBuffer buf, int headerOffset) {
- return (byte) ((buf.get(headerOffset) & (byte) 0xf0) >> 4);
- }
-
- public static short ipChecksum(ByteBuffer buf, int headerOffset) {
- byte ihl = (byte) (buf.get(headerOffset) & 0x0f);
- return (short) checksum(buf, 0, headerOffset, headerOffset + ihl * 4);
- }
-
- private static short transportChecksum(ByteBuffer buf, int protocol,
- int ipOffset, int transportOffset, int transportLen) {
- if (transportLen < 0) {
- throw new IllegalArgumentException("Transport length < 0: " + transportLen);
- }
- int sum;
- byte ver = ipversion(buf, ipOffset);
- if (ver == 4) {
- sum = pseudoChecksumIPv4(buf, ipOffset, protocol, transportLen);
- } else if (ver == 6) {
- sum = pseudoChecksumIPv6(buf, ipOffset, protocol, transportLen);
- } else {
- throw new UnsupportedOperationException("Checksum must be IPv4 or IPv6");
- }
-
- sum = checksum(buf, sum, transportOffset, transportOffset + transportLen);
- if (protocol == IPPROTO_UDP && sum == 0) {
- sum = (short) 0xffff;
- }
- return (short) sum;
- }
-
- public static short udpChecksum(ByteBuffer buf, int ipOffset, int transportOffset) {
- int transportLen = intAbs(buf.getShort(transportOffset + 4));
- return transportChecksum(buf, IPPROTO_UDP, ipOffset, transportOffset, transportLen);
- }
-
- public static short tcpChecksum(ByteBuffer buf, int ipOffset, int transportOffset,
- int transportLen) {
- return transportChecksum(buf, IPPROTO_TCP, ipOffset, transportOffset, transportLen);
- }
-
- public static String addressAndPortToString(InetAddress address, int port) {
- return String.format(
- (address instanceof Inet6Address) ? "[%s]:%d" : "%s:%d",
- address.getHostAddress(), port);
- }
-
- public static boolean isValidUdpOrTcpPort(int port) {
- return port > 0 && port < 65536;
- }
-}
diff --git a/core/java/android/permission/Permissions.md b/core/java/android/permission/Permissions.md
index d8ab618..0495495 100644
--- a/core/java/android/permission/Permissions.md
+++ b/core/java/android/permission/Permissions.md
@@ -203,7 +203,7 @@
During development and testing a runtime permission can be granted via the `pm` shell command or by
using the `UiAutomator.grantRuntimePermission` API call. Please note that this does _not_ grant the
-[app-op](#runtime-permissions-and-app-ops) synchronously. Unless the app needs to test the actual
+[app-op](#runtime-permissions-and-app_ops) synchronously. Unless the app needs to test the actual
permission grant flow it is recommended to grant the runtime permissions during install using
`adb install -g /my/package.apk`.
@@ -262,7 +262,7 @@
silently fail.
A secondary use case of the `AppOpsManager.noteOp` calls is to
-[track](../app/AppOps.md#Appops-for-tracking) which apps perform what runtime protected actions.
+[track](../app/AppOps.md#app_ops-for-tracking) which apps perform what runtime protected actions.
#### Verifying an app has a runtime time permission
@@ -471,7 +471,7 @@
##### Location
-As described [above](#runtime-permissions-and-app-ops) the app-op mode for granted permissions is
+As described [above](#runtime-permissions-and-app_ops) the app-op mode for granted permissions is
`MODE_ALLOWED` to allow access or `MODE_IGNORED` to suppress access.
The important case is the case where the permission is granted and the app-op is `MODE_IGNORED`. In
diff --git a/core/java/android/provider/CalendarContract.java b/core/java/android/provider/CalendarContract.java
index e1aa21e..8ac1d84e 100644
--- a/core/java/android/provider/CalendarContract.java
+++ b/core/java/android/provider/CalendarContract.java
@@ -2618,7 +2618,8 @@
intent.setData(ContentUris.withAppendedId(CalendarContract.CONTENT_URI, alarmTime));
intent.putExtra(ALARM_TIME, alarmTime);
intent.setFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
- PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, 0);
+ PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent,
+ PendingIntent.FLAG_IMMUTABLE);
manager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, alarmTime, pi);
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index b383b6e..7df9a5f 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -14536,6 +14536,15 @@
public static final String SHOW_PEOPLE_SPACE = "show_people_space";
/**
+ * Whether to show new lockscreen & AOD UI.
+ * Values are:
+ * 0: Disabled (default)
+ * 1: Enabled
+ * @hide
+ */
+ public static final String SHOW_NEW_LOCKSCREEN = "show_new_lockscreen";
+
+ /**
* Block untrusted touches mode.
*
* Can be one of:
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 5d34c47..ebd114a 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -64,6 +64,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.Objects;
@@ -1802,7 +1803,7 @@
* {@link NotificationAssistantService}
*/
public @NonNull List<Notification.Action> getSmartActions() {
- return mSmartActions;
+ return mSmartActions == null ? Collections.emptyList() : mSmartActions;
}
/**
@@ -1810,7 +1811,7 @@
* {@link NotificationAssistantService}
*/
public @NonNull List<CharSequence> getSmartReplies() {
- return mSmartReplies;
+ return mSmartReplies == null ? Collections.emptyList() : mSmartReplies;
}
/**
diff --git a/core/java/android/uwb/UwbManager.java b/core/java/android/uwb/UwbManager.java
new file mode 100644
index 0000000..8097dc6
--- /dev/null
+++ b/core/java/android/uwb/UwbManager.java
@@ -0,0 +1,269 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.uwb;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.SuppressLint;
+import android.os.PersistableBundle;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.Executor;
+
+/**
+ * This class provides a way to perform Ultra Wideband (UWB) operations such as querying the
+ * device's capabilities and determining the distance and angle between the local device and a
+ * remote device.
+ *
+ * <p>To get a {@link UwbManager}, call the <code>Context.getSystemService(UwbManager.class)</code>.
+ *
+ * @hide
+ */
+public final class UwbManager {
+ /**
+ * Interface for receiving UWB adapter state changes
+ */
+ public interface AdapterStateCallback {
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = {
+ STATE_CHANGED_REASON_SESSION_STARTED,
+ STATE_CHANGED_REASON_ALL_SESSIONS_CLOSED,
+ STATE_CHANGED_REASON_SYSTEM_POLICY,
+ STATE_CHANGED_REASON_SYSTEM_BOOT,
+ STATE_CHANGED_REASON_ERROR_UNKNOWN})
+ @interface StateChangedReason {}
+
+ /**
+ * Indicates that the state change was due to opening of first UWB session
+ */
+ int STATE_CHANGED_REASON_SESSION_STARTED = 0;
+
+ /**
+ * Indicates that the state change was due to closure of all UWB sessions
+ */
+ int STATE_CHANGED_REASON_ALL_SESSIONS_CLOSED = 1;
+
+ /**
+ * Indicates that the state change was due to changes in system policy
+ */
+ int STATE_CHANGED_REASON_SYSTEM_POLICY = 2;
+
+ /**
+ * Indicates that the current state is due to a system boot
+ */
+ int STATE_CHANGED_REASON_SYSTEM_BOOT = 3;
+
+ /**
+ * Indicates that the state change was due to some unknown error
+ */
+ int STATE_CHANGED_REASON_ERROR_UNKNOWN = 4;
+
+ /**
+ * Invoked when underlying UWB adapter's state is changed
+ * <p>Invoked with the adapter's current state after registering an
+ * {@link AdapterStateCallback} using
+ * {@link UwbManager#registerAdapterStateCallback(Executor, AdapterStateCallback)}.
+ *
+ * <p>Possible values for the state to change are
+ * {@link #STATE_CHANGED_REASON_SESSION_STARTED},
+ * {@link #STATE_CHANGED_REASON_ALL_SESSIONS_CLOSED},
+ * {@link #STATE_CHANGED_REASON_SYSTEM_POLICY},
+ * {@link #STATE_CHANGED_REASON_SYSTEM_BOOT},
+ * {@link #STATE_CHANGED_REASON_ERROR_UNKNOWN}.
+ *
+ * @param isEnabled true when UWB adapter is enabled, false when it is disabled
+ * @param reason the reason for the state change
+ */
+ void onStateChanged(boolean isEnabled, @StateChangedReason int reason);
+ }
+
+ /**
+ * Use <code>Context.getSystemService(UwbManager.class)</code> to get an instance.
+ */
+ private UwbManager() {
+ throw new UnsupportedOperationException();
+ }
+ /**
+ * Register an {@link AdapterStateCallback} to listen for UWB adapter state changes
+ * <p>The provided callback will be invoked by the given {@link Executor}.
+ *
+ * <p>When first registering a callback, the callbacks's
+ * {@link AdapterStateCallback#onStateChanged(boolean, int)} is immediately invoked to indicate
+ * the current state of the underlying UWB adapter with the most recent
+ * {@link AdapterStateCallback.StateChangedReason} that caused the change.
+ *
+ * @param executor an {@link Executor} to execute given callback
+ * @param callback user implementation of the {@link AdapterStateCallback}
+ */
+ public void registerAdapterStateCallback(Executor executor, AdapterStateCallback callback) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Unregister the specified {@link AdapterStateCallback}
+ * <p>The same {@link AdapterStateCallback} object used when calling
+ * {@link #registerAdapterStateCallback(Executor, AdapterStateCallback)} must be used.
+ *
+ * <p>Callbacks are automatically unregistered when application process goes away
+ *
+ * @param callback user implementation of the {@link AdapterStateCallback}
+ */
+ public void unregisterAdapterStateCallback(AdapterStateCallback callback) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Get a {@link PersistableBundle} with the supported UWB protocols and parameters.
+ * <p>The {@link PersistableBundle} should be parsed using a support library
+ *
+ * <p>Android reserves the '^android.*' namespace</p>
+ *
+ * @return {@link PersistableBundle} of the device's supported UWB protocols and parameters
+ */
+ @NonNull
+ public PersistableBundle getSpecificationInfo() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Check if ranging is supported, regardless of ranging method
+ *
+ * @return true if ranging is supported
+ */
+ public boolean isRangingSupported() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = {
+ ANGLE_OF_ARRIVAL_SUPPORT_TYPE_NONE,
+ ANGLE_OF_ARRIVAL_SUPPORT_TYPE_2D,
+ ANGLE_OF_ARRIVAL_SUPPORT_TYPE_3D_HEMISPHERICAL,
+ ANGLE_OF_ARRIVAL_SUPPORT_TYPE_3D_SPHERICAL})
+ public @interface AngleOfArrivalSupportType {}
+
+ /**
+ * Indicate absence of support for angle of arrival measurement
+ */
+ public static final int ANGLE_OF_ARRIVAL_SUPPORT_TYPE_NONE = 1;
+
+ /**
+ * Indicate support for planar angle of arrival measurement, due to antenna
+ * limitation. Typically requires at least two antennas.
+ */
+ public static final int ANGLE_OF_ARRIVAL_SUPPORT_TYPE_2D = 2;
+
+ /**
+ * Indicate support for three dimensional angle of arrival measurement.
+ * Typically requires at least three antennas. However, due to antenna
+ * arrangement, a platform may only support hemi-spherical azimuth angles
+ * ranging from -pi/2 to pi/2
+ */
+ public static final int ANGLE_OF_ARRIVAL_SUPPORT_TYPE_3D_HEMISPHERICAL = 2;
+
+ /**
+ * Indicate support for three dimensional angle of arrival measurement.
+ * Typically requires at least three antennas. This mode supports full
+ * azimuth angles ranging from -pi to pi.
+ */
+ public static final int ANGLE_OF_ARRIVAL_SUPPORT_TYPE_3D_SPHERICAL = 3;
+
+
+ /**
+ * Gets the {@link AngleOfArrivalSupportType} supported on this platform
+ * <p>Possible return values are
+ * {@link #ANGLE_OF_ARRIVAL_SUPPORT_TYPE_NONE},
+ * {@link #ANGLE_OF_ARRIVAL_SUPPORT_TYPE_2D},
+ * {@link #ANGLE_OF_ARRIVAL_SUPPORT_TYPE_3D_HEMISPHERICAL},
+ * {@link #ANGLE_OF_ARRIVAL_SUPPORT_TYPE_3D_SPHERICAL}.
+ *
+ * @return angle of arrival type supported
+ */
+ @AngleOfArrivalSupportType
+ public int getAngleOfArrivalSupport() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Get a {@link List} of supported channel numbers based on the device's current location
+ * <p>The returned values are ordered by the system's desired ordered of use, with the first
+ * entry being the most preferred.
+ *
+ * <p>Channel numbers are defined based on the IEEE 802.15.4z standard for UWB.
+ *
+ * @return {@link List} of supported channel numbers ordered by preference
+ */
+ @NonNull
+ public List<Integer> getSupportedChannelNumbers() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Get a {@link List} of supported preamble code indices
+ * <p> Preamble code indices are defined based on the IEEE 802.15.4z standard for UWB.
+ *
+ * @return {@link List} of supported preamble code indices
+ */
+ @NonNull
+ public Set<Integer> getSupportedPreambleCodeIndices() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Get the timestamp resolution for events in nanoseconds
+ * <p>This value defines the maximum error of all timestamps for events reported to
+ * {@link RangingSession.Callback}.
+ *
+ * @return the timestamp resolution in nanoseconds
+ */
+ @SuppressLint("MethodNameUnits")
+ public long elapsedRealtimeResolutionNanos() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Get the number of simultaneous sessions allowed in the system
+ *
+ * @return the maximum allowed number of simultaneously open {@link RangingSession} instances.
+ */
+ public int getMaxSimultaneousSessions() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Get the maximum number of remote devices in a {@link RangingSession} when the local device
+ * is the initiator.
+ *
+ * @return the maximum number of remote devices per {@link RangingSession}
+ */
+ public int getMaxRemoteDevicesPerInitiatorSession() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Get the maximum number of remote devices in a {@link RangingSession} when the local device
+ * is a responder.
+ *
+ * @return the maximum number of remote devices per {@link RangingSession}
+ */
+ public int getMaxRemoteDevicesPerResponderSession() {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/core/java/com/android/internal/os/KernelSingleProcessCpuThreadReader.java b/core/java/com/android/internal/os/KernelSingleProcessCpuThreadReader.java
index 4f687f1..e6a9623 100644
--- a/core/java/com/android/internal/os/KernelSingleProcessCpuThreadReader.java
+++ b/core/java/com/android/internal/os/KernelSingleProcessCpuThreadReader.java
@@ -45,6 +45,7 @@
private static final String TAG = "KernelSingleProcCpuThreadRdr";
private static final boolean DEBUG = false;
+ private static final boolean NATIVE_ENABLED = true;
/**
* The name of the file to read CPU statistics from, must be found in {@code
@@ -64,7 +65,7 @@
private static final Path INITIAL_TIME_IN_STATE_PATH = Paths.get("self/time_in_state");
/** See https://man7.org/linux/man-pages/man5/proc.5.html */
- private static final int[] PROCESS_FULL_STATS_FORMAT = new int[]{
+ private static final int[] PROCESS_FULL_STATS_FORMAT = new int[] {
PROC_SPACE_TERM,
PROC_SPACE_TERM,
PROC_SPACE_TERM,
@@ -162,6 +163,7 @@
/**
* Get the total and per-thread CPU usage of the process with the PID specified in the
* constructor.
+ *
* @param selectedThreadIds a SORTED array of native Thread IDs whose CPU times should
* be aggregated as a group. This is expected to be a subset
* of all thread IDs owned by the process.
@@ -173,6 +175,20 @@
+ mPid);
}
+ int cpuFrequencyCount = getCpuFrequencyCount();
+ ProcessCpuUsage processCpuUsage = new ProcessCpuUsage(cpuFrequencyCount);
+
+ if (NATIVE_ENABLED) {
+ boolean result = readProcessCpuUsage(mProcPath.toString(), mPid,
+ selectedThreadIds, processCpuUsage.processCpuTimesMillis,
+ processCpuUsage.threadCpuTimesMillis,
+ processCpuUsage.selectedThreadCpuTimesMillis);
+ if (!result) {
+ return null;
+ }
+ return processCpuUsage;
+ }
+
if (!isSorted(selectedThreadIds)) {
throw new IllegalArgumentException("selectedThreadIds is not sorted: "
+ Arrays.toString(selectedThreadIds));
@@ -189,8 +205,6 @@
long processCpuTimeMillis = (utime + stime) * mJiffyMillis;
- int cpuFrequencyCount = getCpuFrequencyCount();
- ProcessCpuUsage processCpuUsage = new ProcessCpuUsage(cpuFrequencyCount);
try (DirectoryStream<Path> threadPaths = Files.newDirectoryStream(mThreadsDirectoryPath)) {
for (Path threadDirectory : threadPaths) {
readThreadCpuUsage(processCpuUsage, selectedThreadIds, threadDirectory);
@@ -274,4 +288,8 @@
}
return true;
}
+
+ private native boolean readProcessCpuUsage(String procPath, int pid, int[] selectedThreadIds,
+ long[] processCpuTimesMillis, long[] threadCpuTimesMillis,
+ long[] selectedThreadCpuTimesMillis);
}
diff --git a/core/java/com/android/internal/view/RecyclerViewCaptureHelper.java b/core/java/com/android/internal/view/RecyclerViewCaptureHelper.java
new file mode 100644
index 0000000..461e116
--- /dev/null
+++ b/core/java/com/android/internal/view/RecyclerViewCaptureHelper.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.view;
+
+import android.animation.ValueAnimator;
+import android.annotation.NonNull;
+import android.graphics.Rect;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewParent;
+
+/**
+ * ScrollCapture for RecyclerView and <i>RecyclerView-like</i> ViewGroups.
+ * <p>
+ * Requirements for proper operation:
+ * <ul>
+ * <li>at least one visible child view</li>
+ * <li>scrolls by pixels in response to {@link View#scrollBy(int, int)}.
+ * <li>reports ability to scroll with {@link View#canScrollVertically(int)}
+ * <li>properly implements {@link ViewParent#requestChildRectangleOnScreen(View, Rect, boolean)}
+ * </ul>
+ *
+ * @see ScrollCaptureViewSupport
+ */
+public class RecyclerViewCaptureHelper implements ScrollCaptureViewHelper<ViewGroup> {
+
+ // Experiment
+ private static final boolean DISABLE_ANIMATORS = false;
+ // Experiment
+ private static final boolean STOP_RENDER_THREAD = false;
+
+ private static final String TAG = "RVCaptureHelper";
+ private int mScrollDelta;
+ private boolean mScrollBarWasEnabled;
+ private int mOverScrollMode;
+ private float mDurationScale;
+
+ @Override
+ public void onPrepareForStart(@NonNull ViewGroup view, Rect scrollBounds) {
+ mScrollDelta = 0;
+
+ mOverScrollMode = view.getOverScrollMode();
+ view.setOverScrollMode(View.OVER_SCROLL_NEVER);
+
+ mScrollBarWasEnabled = view.isVerticalScrollBarEnabled();
+ view.setVerticalScrollBarEnabled(false);
+ if (DISABLE_ANIMATORS) {
+ mDurationScale = ValueAnimator.getDurationScale();
+ ValueAnimator.setDurationScale(0);
+ }
+ if (STOP_RENDER_THREAD) {
+ view.getThreadedRenderer().stop();
+ }
+ }
+
+ @Override
+ public ScrollResult onScrollRequested(@NonNull ViewGroup recyclerView, Rect scrollBounds,
+ Rect requestRect) {
+ ScrollResult result = new ScrollResult();
+ result.requestedArea = new Rect(requestRect);
+ result.scrollDelta = mScrollDelta;
+ result.availableArea = new Rect(); // empty
+
+ Log.d(TAG, "current scrollDelta: " + mScrollDelta);
+ if (!recyclerView.isVisibleToUser() || recyclerView.getChildCount() == 0) {
+ Log.w(TAG, "recyclerView is empty or not visible, cannot continue");
+ return result; // result.availableArea == empty Rect
+ }
+
+ // move from scrollBounds-relative to parent-local coordinates
+ Rect requestedContainerBounds = new Rect(requestRect);
+ requestedContainerBounds.offset(0, -mScrollDelta);
+ requestedContainerBounds.offset(scrollBounds.left, scrollBounds.top);
+
+ // requestedContainerBounds is now in recyclerview-local coordinates
+ Log.d(TAG, "requestedContainerBounds: " + requestedContainerBounds);
+
+ // Save a copy for later
+ View anchor = findChildNearestTarget(recyclerView, requestedContainerBounds);
+ if (anchor == null) {
+ Log.d(TAG, "Failed to locate anchor view");
+ return result; // result.availableArea == null
+ }
+
+ Log.d(TAG, "Anchor view:" + anchor);
+ Rect requestedContentBounds = new Rect(requestedContainerBounds);
+ recyclerView.offsetRectIntoDescendantCoords(anchor, requestedContentBounds);
+
+ Log.d(TAG, "requestedContentBounds = " + requestedContentBounds);
+ int prevAnchorTop = anchor.getTop();
+ // Note: requestChildRectangleOnScreen may modify rectangle, must pass pass in a copy here
+ Rect input = new Rect(requestedContentBounds);
+ if (recyclerView.requestChildRectangleOnScreen(anchor, input, true)) {
+ int scrolled = prevAnchorTop - anchor.getTop(); // inverse of movement
+ Log.d(TAG, "RecyclerView scrolled by " + scrolled + " px");
+ mScrollDelta += scrolled; // view.top-- is equivalent to parent.scrollY++
+ result.scrollDelta = mScrollDelta;
+ Log.d(TAG, "requestedContentBounds, (post-request-rect) = " + requestedContentBounds);
+ }
+
+ requestedContainerBounds.set(requestedContentBounds);
+ recyclerView.offsetDescendantRectToMyCoords(anchor, requestedContainerBounds);
+ Log.d(TAG, "requestedContainerBounds, (post-scroll): " + requestedContainerBounds);
+
+ Rect recyclerLocalVisible = new Rect(scrollBounds);
+ recyclerView.getLocalVisibleRect(recyclerLocalVisible);
+ Log.d(TAG, "recyclerLocalVisible: " + recyclerLocalVisible);
+
+ if (!requestedContainerBounds.intersect(recyclerLocalVisible)) {
+ // Requested area is still not visible
+ Log.d(TAG, "requested bounds not visible!");
+ return result;
+ }
+ Rect available = new Rect(requestedContainerBounds);
+ available.offset(-scrollBounds.left, -scrollBounds.top);
+ available.offset(0, mScrollDelta);
+ result.availableArea = available;
+ Log.d(TAG, "availableArea: " + result.availableArea);
+ return result;
+ }
+
+ /**
+ * Find a view that is located "closest" to targetRect. Returns the first view to fully
+ * vertically overlap the target targetRect. If none found, returns the view with an edge
+ * nearest the target targetRect.
+ *
+ * @param parent the parent vertical layout
+ * @param targetRect a rectangle in local coordinates of <code>parent</code>
+ * @return a child view within parent matching the criteria or null
+ */
+ static View findChildNearestTarget(ViewGroup parent, Rect targetRect) {
+ View selected = null;
+ int minCenterDistance = Integer.MAX_VALUE;
+ int maxOverlap = 0;
+
+ // allowable center-center distance, relative to targetRect.
+ // if within this range, taller views are preferred
+ final float preferredRangeFromCenterPercent = 0.25f;
+ final int preferredDistance =
+ (int) (preferredRangeFromCenterPercent * targetRect.height());
+
+ Rect parentLocalVis = new Rect();
+ parent.getLocalVisibleRect(parentLocalVis);
+ Log.d(TAG, "findChildNearestTarget: parentVis=" + parentLocalVis
+ + " targetRect=" + targetRect);
+
+ Rect frame = new Rect();
+ for (int i = 0; i < parent.getChildCount(); i++) {
+ final View child = parent.getChildAt(i);
+ child.getHitRect(frame);
+ Log.d(TAG, "child #" + i + " hitRect=" + frame);
+
+ if (child.getVisibility() != View.VISIBLE) {
+ Log.d(TAG, "child #" + i + " is not visible");
+ continue;
+ }
+
+ int centerDistance = Math.abs(targetRect.centerY() - frame.centerY());
+ Log.d(TAG, "child #" + i + " : center to center: " + centerDistance + "px");
+
+ if (centerDistance < minCenterDistance) {
+ // closer to center
+ minCenterDistance = centerDistance;
+ selected = child;
+ } else if (frame.intersect(targetRect) && (frame.height() > preferredDistance)) {
+ // within X% pixels of center, but taller
+ selected = child;
+ }
+ }
+ return selected;
+ }
+
+
+ @Override
+ public void onPrepareForEnd(@NonNull ViewGroup view) {
+ // Restore original position and state
+ view.scrollBy(0, mScrollDelta);
+ view.setOverScrollMode(mOverScrollMode);
+ view.setVerticalScrollBarEnabled(mScrollBarWasEnabled);
+ if (DISABLE_ANIMATORS) {
+ ValueAnimator.setDurationScale(mDurationScale);
+ }
+ if (STOP_RENDER_THREAD) {
+ view.getThreadedRenderer().start();
+ }
+ }
+}
diff --git a/core/java/com/android/internal/view/ScrollCaptureInternal.java b/core/java/com/android/internal/view/ScrollCaptureInternal.java
index c589afde..ae1a815 100644
--- a/core/java/com/android/internal/view/ScrollCaptureInternal.java
+++ b/core/java/com/android/internal/view/ScrollCaptureInternal.java
@@ -17,8 +17,11 @@
package com.android.internal.view;
import android.annotation.Nullable;
+import android.content.Context;
+import android.content.res.Resources;
import android.graphics.Point;
import android.graphics.Rect;
+import android.util.Log;
import android.view.ScrollCaptureCallback;
import android.view.View;
import android.view.ViewGroup;
@@ -29,6 +32,12 @@
public class ScrollCaptureInternal {
private static final String TAG = "ScrollCaptureInternal";
+ // Log found scrolling views
+ private static final boolean DEBUG = true;
+
+ // Log all investigated views, as well as heuristic checks
+ private static final boolean DEBUG_VERBOSE = false;
+
private static final int UP = -1;
private static final int DOWN = 1;
@@ -57,38 +66,72 @@
* This needs to be fast and not alloc memory. It's called on everything in the tree not marked
* as excluded during scroll capture search.
*/
- public static int detectScrollingType(View view) {
+ private static int detectScrollingType(View view) {
// Must be a ViewGroup
if (!(view instanceof ViewGroup)) {
+ if (DEBUG_VERBOSE) {
+ Log.v(TAG, "hint: not a subclass of ViewGroup");
+ }
return TYPE_FIXED;
}
+ if (DEBUG_VERBOSE) {
+ Log.v(TAG, "hint: is a subclass of ViewGroup");
+ }
// Confirm that it can scroll.
if (!(view.canScrollVertically(DOWN) || view.canScrollVertically(UP))) {
// Nothing to scroll here, move along.
+ if (DEBUG_VERBOSE) {
+ Log.v(TAG, "hint: cannot be scrolled");
+ }
return TYPE_FIXED;
}
+ if (DEBUG_VERBOSE) {
+ Log.v(TAG, "hint: can be scrolled up or down");
+ }
// ScrollViews accept only a single child.
if (((ViewGroup) view).getChildCount() > 1) {
+ if (DEBUG_VERBOSE) {
+ Log.v(TAG, "hint: scrollable with multiple children");
+ }
return TYPE_RECYCLING;
}
+ if (DEBUG_VERBOSE) {
+ Log.v(TAG, "hint: less than two child views");
+ }
//Because recycling containers don't use scrollY, a non-zero value means Scroll view.
if (view.getScrollY() != 0) {
+ if (DEBUG_VERBOSE) {
+ Log.v(TAG, "hint: scrollY != 0");
+ }
return TYPE_SCROLLING;
}
+ Log.v(TAG, "hint: scrollY == 0");
// Since scrollY cannot be negative, this means a Recycling view.
if (view.canScrollVertically(UP)) {
+ if (DEBUG_VERBOSE) {
+ Log.v(TAG, "hint: able to scroll up");
+ }
return TYPE_RECYCLING;
}
- // canScrollVertically(UP) == false, getScrollY() == 0, getChildCount() == 1.
+ if (DEBUG_VERBOSE) {
+ Log.v(TAG, "hint: cannot be scrolled up");
+ }
+ // canScrollVertically(UP) == false, getScrollY() == 0, getChildCount() == 1.
// For Recycling containers, this should be a no-op (RecyclerView logs a warning)
view.scrollTo(view.getScrollX(), 1);
// A scrolling container would have moved by 1px.
if (view.getScrollY() == 1) {
view.scrollTo(view.getScrollX(), 0);
+ if (DEBUG_VERBOSE) {
+ Log.v(TAG, "hint: scrollTo caused scrollY to change");
+ }
return TYPE_SCROLLING;
}
+ if (DEBUG_VERBOSE) {
+ Log.v(TAG, "hint: scrollTo did not cause scrollY to change");
+ }
return TYPE_RECYCLING;
}
@@ -99,19 +142,61 @@
* @param localVisibleRect the visible area of the given view in local coordinates, as supplied
* by the view parent
* @param positionInWindow the offset of localVisibleRect within the window
- *
* @return a new callback or null if the View isn't supported
*/
@Nullable
public ScrollCaptureCallback requestCallback(View view, Rect localVisibleRect,
Point positionInWindow) {
// Nothing to see here yet.
+ if (DEBUG_VERBOSE) {
+ Log.v(TAG, "scroll capture: checking " + view.getClass().getName()
+ + "[" + resolveId(view.getContext(), view.getId()) + "]");
+ }
int i = detectScrollingType(view);
switch (i) {
case TYPE_SCROLLING:
+ if (DEBUG) {
+ Log.d(TAG, "scroll capture: FOUND " + view.getClass().getName()
+ + "[" + resolveId(view.getContext(), view.getId()) + "]"
+ + " -> TYPE_SCROLLING");
+ }
return new ScrollCaptureViewSupport<>((ViewGroup) view,
new ScrollViewCaptureHelper());
+ case TYPE_RECYCLING:
+ if (DEBUG) {
+ Log.d(TAG, "scroll capture: FOUND " + view.getClass().getName()
+ + "[" + resolveId(view.getContext(), view.getId()) + "]"
+ + " -> TYPE_RECYCLING");
+ }
+ return new ScrollCaptureViewSupport<>((ViewGroup) view,
+ new RecyclerViewCaptureHelper());
+ case TYPE_FIXED:
+ // ignore
+ break;
+
}
return null;
}
+
+ // Lifted from ViewDebug (package protected)
+
+ private static String formatIntToHexString(int value) {
+ return "0x" + Integer.toHexString(value).toUpperCase();
+ }
+
+ static String resolveId(Context context, int id) {
+ String fieldValue;
+ final Resources resources = context.getResources();
+ if (id >= 0) {
+ try {
+ fieldValue = resources.getResourceTypeName(id) + '/'
+ + resources.getResourceEntryName(id);
+ } catch (Resources.NotFoundException e) {
+ fieldValue = "id/" + formatIntToHexString(id);
+ }
+ } else {
+ fieldValue = "NO_ID";
+ }
+ return fieldValue;
+ }
}
diff --git a/core/java/com/android/internal/view/ScrollCaptureViewHelper.java b/core/java/com/android/internal/view/ScrollCaptureViewHelper.java
index a92e978..9829d0b 100644
--- a/core/java/com/android/internal/view/ScrollCaptureViewHelper.java
+++ b/core/java/com/android/internal/view/ScrollCaptureViewHelper.java
@@ -17,7 +17,6 @@
package com.android.internal.view;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.graphics.Rect;
import android.view.View;
@@ -62,8 +61,8 @@
* @param view the view being captured
* @return true if the callback should respond to a request with scroll bounds
*/
- default boolean onAcceptSession(@Nullable V view) {
- return view != null && view.isVisibleToUser()
+ default boolean onAcceptSession(@NonNull V view) {
+ return view.isVisibleToUser()
&& (view.canScrollVertically(UP) || view.canScrollVertically(DOWN));
}
@@ -73,7 +72,7 @@
*
* @param view the view being captured
*/
- default Rect onComputeScrollBounds(@Nullable V view) {
+ @NonNull default Rect onComputeScrollBounds(@NonNull V view) {
return new Rect(view.getPaddingLeft(), view.getPaddingTop(),
view.getWidth() - view.getPaddingRight(),
view.getHeight() - view.getPaddingBottom());
@@ -88,7 +87,7 @@
* @param view the view being captured
* @param scrollBounds the bounds within {@code view} where content scrolls
*/
- void onPrepareForStart(@NonNull V view, Rect scrollBounds);
+ void onPrepareForStart(@NonNull V view, @NonNull Rect scrollBounds);
/**
* Map the request onto the screen.
@@ -105,7 +104,9 @@
* content to capture for the request
* @return the result of the request as a {@link ScrollResult}
*/
- ScrollResult onScrollRequested(@NonNull V view, Rect scrollBounds, Rect requestRect);
+ @NonNull
+ ScrollResult onScrollRequested(@NonNull V view, @NonNull Rect scrollBounds,
+ @NonNull Rect requestRect);
/**
* Restore the target after capture.
diff --git a/core/java/com/android/internal/view/ScrollCaptureViewSupport.java b/core/java/com/android/internal/view/ScrollCaptureViewSupport.java
index 7b4f73f..85fa791 100644
--- a/core/java/com/android/internal/view/ScrollCaptureViewSupport.java
+++ b/core/java/com/android/internal/view/ScrollCaptureViewSupport.java
@@ -23,8 +23,8 @@
import android.graphics.RectF;
import android.graphics.RenderNode;
import android.os.Handler;
-import android.os.SystemClock;
import android.util.DisplayMetrics;
+import android.util.Log;
import android.view.ScrollCaptureCallback;
import android.view.ScrollCaptureSession;
import android.view.Surface;
@@ -46,8 +46,12 @@
*/
public class ScrollCaptureViewSupport<V extends View> implements ScrollCaptureCallback {
+ public static final long NO_FRAME_PRODUCED = -1;
+
private static final String TAG = "ScrollCaptureViewSupport";
+ private static final boolean WAIT_FOR_ANIMATION = true;
+
private final WeakReference<V> mWeakView;
private final ScrollCaptureViewHelper<V> mViewHelper;
private ViewRenderer mRenderer;
@@ -99,12 +103,16 @@
V view = mWeakView.get();
if (view == null || !view.isVisibleToUser()) {
// Signal to the controller that we have a problem and can't continue.
- session.notifyBufferSent(0, null);
+ session.notifyBufferSent(NO_FRAME_PRODUCED, new Rect());
return;
}
// Ask the view to scroll as needed to bring this area into view.
ScrollResult scrollResult = mViewHelper.onScrollRequested(view, session.getScrollBounds(),
requestRect);
+ if (scrollResult.availableArea.isEmpty()) {
+ session.notifyBufferSent(NO_FRAME_PRODUCED, scrollResult.availableArea);
+ return;
+ }
view.invalidate(); // don't wait for vsync
// For image capture, shift back by scrollDelta to arrive at the location within the view
@@ -112,8 +120,19 @@
Rect viewCaptureArea = new Rect(scrollResult.availableArea);
viewCaptureArea.offset(0, -scrollResult.scrollDelta);
- mRenderer.renderView(view, viewCaptureArea, mUiHandler,
- (frameNumber) -> session.notifyBufferSent(frameNumber, scrollResult.availableArea));
+ if (WAIT_FOR_ANIMATION) {
+ Log.d(TAG, "render: delaying until animation");
+ view.postOnAnimation(() -> {
+ Log.d(TAG, "postOnAnimation(): rendering now");
+ long resultFrame = mRenderer.renderView(view, viewCaptureArea);
+ Log.d(TAG, "notifyBufferSent: " + scrollResult.availableArea);
+
+ session.notifyBufferSent(resultFrame, new Rect(scrollResult.availableArea));
+ });
+ } else {
+ long resultFrame = mRenderer.renderView(view, viewCaptureArea);
+ session.notifyBufferSent(resultFrame, new Rect(scrollResult.availableArea));
+ }
}
@Override
@@ -132,8 +151,7 @@
/**
* Internal helper class which assists in rendering sections of the view hierarchy relative to a
- * given view. Used by framework implementations of ScrollCaptureHandler to render and dispatch
- * image requests.
+ * given view.
*/
static final class ViewRenderer {
// alpha, "reasonable default" from Javadoc
@@ -157,14 +175,11 @@
private final Matrix mTempMatrix = new Matrix();
private final int[] mTempLocation = new int[2];
private long mLastRenderedSourceDrawingId = -1;
-
-
- public interface FrameCompleteListener {
- void onFrameComplete(long frameNumber);
- }
+ private Surface mSurface;
ViewRenderer() {
mRenderer = new HardwareRenderer();
+ mRenderer.setName("ScrollCapture");
mCaptureRenderNode = new RenderNode("ScrollCaptureRoot");
mRenderer.setContentRoot(mCaptureRenderNode);
@@ -173,6 +188,7 @@
}
public void setSurface(Surface surface) {
+ mSurface = surface;
mRenderer.setSurface(surface);
}
@@ -223,20 +239,38 @@
mCaptureRenderNode.endRecording();
}
- public void renderView(View view, Rect sourceRect, Handler handler,
- FrameCompleteListener frameListener) {
+ public long renderView(View view, Rect sourceRect) {
if (updateForView(view)) {
setupLighting(view);
}
view.invalidate();
updateRootNode(view, sourceRect);
HardwareRenderer.FrameRenderRequest request = mRenderer.createRenderRequest();
- request.setVsyncTime(SystemClock.elapsedRealtimeNanos());
- // private API b/c request.setFrameCommitCallback does not provide access to frameNumber
- mRenderer.setFrameCompleteCallback(
- frameNr -> handler.post(() -> frameListener.onFrameComplete(frameNr)));
+ long timestamp = System.nanoTime();
+ request.setVsyncTime(timestamp);
+
+ // Would be nice to access nextFrameNumber from HwR without having to hold on to Surface
+ final long frameNumber = mSurface.getNextFrameNumber();
+
+ // Block until a frame is presented to the Surface
request.setWaitForPresent(true);
- request.syncAndDraw();
+
+ switch (request.syncAndDraw()) {
+ case HardwareRenderer.SYNC_OK:
+ case HardwareRenderer.SYNC_REDRAW_REQUESTED:
+ return frameNumber;
+
+ case HardwareRenderer.SYNC_FRAME_DROPPED:
+ Log.e(TAG, "syncAndDraw(): SYNC_FRAME_DROPPED !");
+ break;
+ case HardwareRenderer.SYNC_LOST_SURFACE_REWARD_IF_FOUND:
+ Log.e(TAG, "syncAndDraw(): SYNC_LOST_SURFACE !");
+ break;
+ case HardwareRenderer.SYNC_CONTEXT_IS_STOPPED:
+ Log.e(TAG, "syncAndDraw(): SYNC_CONTEXT_IS_STOPPED !");
+ break;
+ }
+ return NO_FRAME_PRODUCED;
}
public void trimMemory() {
@@ -244,6 +278,7 @@
}
public void destroy() {
+ mSurface = null;
mRenderer.destroy();
}
@@ -254,6 +289,5 @@
mTempMatrix.mapRect(mTempRectF);
mTempRectF.round(outRect);
}
-
}
}
diff --git a/core/java/com/android/internal/view/ScrollViewCaptureHelper.java b/core/java/com/android/internal/view/ScrollViewCaptureHelper.java
index 1514b9a..a1d202e 100644
--- a/core/java/com/android/internal/view/ScrollViewCaptureHelper.java
+++ b/core/java/com/android/internal/view/ScrollViewCaptureHelper.java
@@ -57,10 +57,6 @@
public ScrollResult onScrollRequested(@NonNull ViewGroup view, Rect scrollBounds,
Rect requestRect) {
- final View contentView = view.getChildAt(0); // returns null, does not throw IOOBE
- if (contentView == null) {
- return null;
- }
/*
+---------+ <----+ Content [25,25 - 275,1025] (w=250,h=1000)
| |
@@ -88,9 +84,6 @@
\__ Requested Bounds[0,300 - 200,400] (200x100)
*/
- ScrollResult result = new ScrollResult();
- result.requestedArea = new Rect(requestRect);
-
// 0) adjust the requestRect to account for scroll change since start
//
// Scroll Bounds[50,50 - 250,250] (w=200,h=200)
@@ -99,6 +92,17 @@
// (y-100) (scrollY - mStartScrollY)
int scrollDelta = view.getScrollY() - mStartScrollY;
+ final ScrollResult result = new ScrollResult();
+ result.requestedArea = new Rect(requestRect);
+ result.scrollDelta = scrollDelta;
+ result.availableArea = new Rect();
+
+ final View contentView = view.getChildAt(0); // returns null, does not throw IOOBE
+ if (contentView == null) {
+ // No child view? Cannot continue.
+ return result;
+ }
+
// 1) Translate request rect to make it relative to container view
//
// Container View [0,0 - 300,300] (scrollY=200)
@@ -133,7 +137,7 @@
// TODO: crop capture area to avoid occlusions/minimize scroll changes
Point offset = new Point();
- final Rect available = new Rect(requestedContentBounds); // empty
+ final Rect available = new Rect(requestedContentBounds);
if (!view.getChildVisibleRect(contentView, available, offset)) {
available.setEmpty();
result.availableArea = available;
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index adb0fad..4f97975 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -184,6 +184,7 @@
"com_android_internal_os_ClassLoaderFactory.cpp",
"com_android_internal_os_FuseAppLoop.cpp",
"com_android_internal_os_KernelCpuUidBpfMapReader.cpp",
+ "com_android_internal_os_KernelSingleProcessCpuThreadReader.cpp",
"com_android_internal_os_KernelSingleUidTimeReader.cpp",
"com_android_internal_os_Zygote.cpp",
"com_android_internal_os_ZygoteInit.cpp",
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 5b1196d..27b23bd 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -189,6 +189,7 @@
extern int register_com_android_internal_os_ClassLoaderFactory(JNIEnv* env);
extern int register_com_android_internal_os_FuseAppLoop(JNIEnv* env);
extern int register_com_android_internal_os_KernelCpuUidBpfMapReader(JNIEnv *env);
+extern int register_com_android_internal_os_KernelSingleProcessCpuThreadReader(JNIEnv* env);
extern int register_com_android_internal_os_KernelSingleUidTimeReader(JNIEnv *env);
extern int register_com_android_internal_os_Zygote(JNIEnv *env);
extern int register_com_android_internal_os_ZygoteInit(JNIEnv *env);
@@ -1581,6 +1582,7 @@
REG_JNI(register_com_android_internal_content_NativeLibraryHelper),
REG_JNI(register_com_android_internal_os_FuseAppLoop),
REG_JNI(register_com_android_internal_os_KernelCpuUidBpfMapReader),
+ REG_JNI(register_com_android_internal_os_KernelSingleProcessCpuThreadReader),
REG_JNI(register_com_android_internal_os_KernelSingleUidTimeReader),
};
diff --git a/core/jni/com_android_internal_os_KernelSingleProcessCpuThreadReader.cpp b/core/jni/com_android_internal_os_KernelSingleProcessCpuThreadReader.cpp
new file mode 100644
index 0000000..52bed6b
--- /dev/null
+++ b/core/jni/com_android_internal_os_KernelSingleProcessCpuThreadReader.cpp
@@ -0,0 +1,269 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "core_jni_helpers.h"
+
+#include <cputimeinstate.h>
+#include <dirent.h>
+
+#include <android-base/file.h>
+#include <android-base/parseint.h>
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
+#include <android_runtime/Log.h>
+
+#include <nativehelper/ScopedPrimitiveArray.h>
+#include <nativehelper/ScopedUtfChars.h>
+
+namespace android {
+
+// Number of milliseconds in a jiffy - the unit of time measurement for processes and threads
+static const uint32_t gJiffyMillis = (uint32_t)(1000 / sysconf(_SC_CLK_TCK));
+
+// Given a PID, returns a vector of all TIDs for the process' tasks. Thread IDs are
+// file names in the /proc/<pid>/task directory.
+static bool getThreadIds(const std::string &procPath, const pid_t pid,
+ std::vector<pid_t> &outThreadIds) {
+ std::string taskPath = android::base::StringPrintf("%s/%u/task", procPath.c_str(), pid);
+
+ struct dirent **dirlist;
+ int threadCount = scandir(taskPath.c_str(), &dirlist, NULL, NULL);
+ if (threadCount == -1) {
+ ALOGE("Cannot read directory %s", taskPath.c_str());
+ return false;
+ }
+
+ outThreadIds.reserve(threadCount);
+
+ for (int i = 0; i < threadCount; i++) {
+ pid_t tid;
+ if (android::base::ParseInt<pid_t>(dirlist[i]->d_name, &tid)) {
+ outThreadIds.push_back(tid);
+ }
+ free(dirlist[i]);
+ }
+ free(dirlist);
+
+ return true;
+}
+
+// Reads contents of a time_in_state file and returns times as a vector of times per frequency
+// A time_in_state file contains pairs of frequency - time (in jiffies):
+//
+// cpu0
+// 300000 30
+// 403200 0
+// cpu4
+// 710400 10
+// 825600 20
+// 940800 30
+//
+static bool getThreadTimeInState(const std::string &procPath, const pid_t pid, const pid_t tid,
+ const size_t frequencyCount,
+ std::vector<uint64_t> &outThreadTimeInState) {
+ std::string timeInStateFilePath =
+ android::base::StringPrintf("%s/%u/task/%u/time_in_state", procPath.c_str(), pid, tid);
+ std::string data;
+
+ if (!android::base::ReadFileToString(timeInStateFilePath, &data)) {
+ ALOGE("Cannot read file: %s", timeInStateFilePath.c_str());
+ return false;
+ }
+
+ auto lines = android::base::Split(data, "\n");
+ size_t index = 0;
+ for (const auto &line : lines) {
+ if (line.empty()) {
+ continue;
+ }
+
+ auto numbers = android::base::Split(line, " ");
+ if (numbers.size() != 2) {
+ continue;
+ }
+ uint64_t timeInState;
+ if (!android::base::ParseUint<uint64_t>(numbers[1], &timeInState)) {
+ ALOGE("Invalid time_in_state file format: %s", timeInStateFilePath.c_str());
+ return false;
+ }
+ if (index < frequencyCount) {
+ outThreadTimeInState[index] = timeInState;
+ }
+ index++;
+ }
+
+ if (index != frequencyCount) {
+ ALOGE("Incorrect number of frequencies %u in %s. Expected %u",
+ (uint32_t)outThreadTimeInState.size(), timeInStateFilePath.c_str(),
+ (uint32_t)frequencyCount);
+ return false;
+ }
+
+ return true;
+}
+
+static int pidCompare(const void *a, const void *b) {
+ return (*(pid_t *)a - *(pid_t *)b);
+}
+
+static inline bool isSelectedThread(const pid_t tid, const pid_t *selectedThreadIds,
+ const size_t selectedThreadCount) {
+ return bsearch(&tid, selectedThreadIds, selectedThreadCount, sizeof(pid_t), pidCompare) != NULL;
+}
+
+// Reads all /proc/<pid>/task/*/time_in_state files and aggregates per-frequency
+// time in state data for all threads. Also, separately aggregates time in state for
+// selected threads whose TIDs are passes as selectedThreadIds.
+static void aggregateThreadCpuTimes(const std::string &procPath, const pid_t pid,
+ const std::vector<pid_t> &threadIds,
+ const size_t frequencyCount, const pid_t *selectedThreadIds,
+ const size_t selectedThreadCount,
+ uint64_t *threadCpuTimesMillis,
+ uint64_t *selectedThreadCpuTimesMillis) {
+ for (size_t j = 0; j < frequencyCount; j++) {
+ threadCpuTimesMillis[j] = 0;
+ selectedThreadCpuTimesMillis[j] = 0;
+ }
+
+ for (size_t i = 0; i < threadIds.size(); i++) {
+ pid_t tid = threadIds[i];
+ std::vector<uint64_t> timeInState(frequencyCount);
+ if (!getThreadTimeInState(procPath, pid, tid, frequencyCount, timeInState)) {
+ continue;
+ }
+
+ bool selectedThread = isSelectedThread(tid, selectedThreadIds, selectedThreadCount);
+ for (size_t j = 0; j < frequencyCount; j++) {
+ threadCpuTimesMillis[j] += timeInState[j];
+ if (selectedThread) {
+ selectedThreadCpuTimesMillis[j] += timeInState[j];
+ }
+ }
+ }
+ for (size_t i = 0; i < frequencyCount; i++) {
+ threadCpuTimesMillis[i] *= gJiffyMillis;
+ selectedThreadCpuTimesMillis[i] *= gJiffyMillis;
+ }
+}
+
+// Reads process utime and stime from the /proc/<pid>/stat file.
+// Format of this file is described in https://man7.org/linux/man-pages/man5/proc.5.html.
+static bool getProcessCpuTime(const std::string &procPath, const pid_t pid,
+ uint64_t &outTimeMillis) {
+ std::string statFilePath = android::base::StringPrintf("%s/%u/stat", procPath.c_str(), pid);
+ std::string data;
+ if (!android::base::ReadFileToString(statFilePath, &data)) {
+ return false;
+ }
+
+ auto fields = android::base::Split(data, " ");
+ uint64_t utime, stime;
+
+ // Field 14 (counting from 1) is utime - process time in user space, in jiffies
+ // Field 15 (counting from 1) is stime - process time in system space, in jiffies
+ if (fields.size() < 15 || !android::base::ParseUint(fields[13], &utime) ||
+ !android::base::ParseUint(fields[14], &stime)) {
+ ALOGE("Invalid file format %s", statFilePath.c_str());
+ return false;
+ }
+
+ outTimeMillis = (utime + stime) * gJiffyMillis;
+ return true;
+}
+
+// Estimates per cluster per frequency CPU time for the entire process
+// by distributing the total process CPU time proportionately to how much
+// CPU time its threads took on those clusters/frequencies. This algorithm
+// works more accurately when when we have equally distributed concurrency.
+// TODO(b/169279846): obtain actual process CPU times from the kernel
+static void estimateProcessTimeInState(const uint64_t processCpuTimeMillis,
+ const uint64_t *threadCpuTimesMillis,
+ const size_t frequencyCount,
+ uint64_t *processCpuTimesMillis) {
+ uint64_t totalCpuTimeAllThreads = 0;
+ for (size_t i = 0; i < frequencyCount; i++) {
+ totalCpuTimeAllThreads += threadCpuTimesMillis[i];
+ }
+
+ if (totalCpuTimeAllThreads != 0) {
+ for (size_t i = 0; i < frequencyCount; i++) {
+ processCpuTimesMillis[i] =
+ processCpuTimeMillis * threadCpuTimesMillis[i] / totalCpuTimeAllThreads;
+ }
+ } else {
+ for (size_t i = 0; i < frequencyCount; i++) {
+ processCpuTimesMillis[i] = 0;
+ }
+ }
+}
+
+static jboolean readProcessCpuUsage(JNIEnv *env, jclass, jstring procPath, jint pid,
+ jintArray selectedThreadIdArray,
+ jlongArray processCpuTimesMillisArray,
+ jlongArray threadCpuTimesMillisArray,
+ jlongArray selectedThreadCpuTimesMillisArray) {
+ ScopedUtfChars procPathChars(env, procPath);
+ ScopedIntArrayRO selectedThreadIds(env, selectedThreadIdArray);
+ ScopedLongArrayRW processCpuTimesMillis(env, processCpuTimesMillisArray);
+ ScopedLongArrayRW threadCpuTimesMillis(env, threadCpuTimesMillisArray);
+ ScopedLongArrayRW selectedThreadCpuTimesMillis(env, selectedThreadCpuTimesMillisArray);
+
+ std::string procPathStr(procPathChars.c_str());
+
+ // Get all thread IDs for the process.
+ std::vector<pid_t> threadIds;
+ if (!getThreadIds(procPathStr, pid, threadIds)) {
+ ALOGE("Could not obtain thread IDs from: %s", procPathStr.c_str());
+ return false;
+ }
+
+ size_t frequencyCount = processCpuTimesMillis.size();
+
+ if (threadCpuTimesMillis.size() != frequencyCount) {
+ ALOGE("Invalid array length: threadCpuTimesMillis");
+ return false;
+ }
+ if (selectedThreadCpuTimesMillis.size() != frequencyCount) {
+ ALOGE("Invalid array length: selectedThreadCpuTimesMillisArray");
+ return false;
+ }
+
+ aggregateThreadCpuTimes(procPathStr, pid, threadIds, frequencyCount, selectedThreadIds.get(),
+ selectedThreadIds.size(),
+ reinterpret_cast<uint64_t *>(threadCpuTimesMillis.get()),
+ reinterpret_cast<uint64_t *>(selectedThreadCpuTimesMillis.get()));
+
+ uint64_t processCpuTime;
+ bool ret = getProcessCpuTime(procPathStr, pid, processCpuTime);
+ if (ret) {
+ estimateProcessTimeInState(processCpuTime,
+ reinterpret_cast<uint64_t *>(threadCpuTimesMillis.get()),
+ frequencyCount,
+ reinterpret_cast<uint64_t *>(processCpuTimesMillis.get()));
+ }
+ return ret;
+}
+
+static const JNINativeMethod g_single_methods[] = {
+ {"readProcessCpuUsage", "(Ljava/lang/String;I[I[J[J[J)Z", (void *)readProcessCpuUsage},
+};
+
+int register_com_android_internal_os_KernelSingleProcessCpuThreadReader(JNIEnv *env) {
+ return RegisterMethodsOrDie(env, "com/android/internal/os/KernelSingleProcessCpuThreadReader",
+ g_single_methods, NELEM(g_single_methods));
+}
+
+} // namespace android
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index ed13069..e2f4f2f 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -3488,6 +3488,14 @@
<permission android:name="android.permission.BIND_CONTENT_SUGGESTIONS_SERVICE"
android:protectionLevel="signature" />
+ <!-- Must be declared by a android.service.musicrecognition.MusicRecognitionService,
+ to ensure that only the system can bind to it.
+ @SystemApi @hide This is not a third-party API (intended for OEMs and system apps).
+ <p>Protection level: signature
+ -->
+ <permission android:name="android.permission.BIND_MUSIC_RECOGNITION_SERVICE"
+ android:protectionLevel="signature" />
+
<!-- Must be required by a android.service.autofill.augmented.AugmentedAutofillService,
to ensure that only the system can bind to it.
@SystemApi @hide This is not a third-party API (intended for OEMs and system apps).
@@ -4533,6 +4541,12 @@
<permission android:name="android.permission.RESET_FINGERPRINT_LOCKOUT"
android:protectionLevel="signature" />
+ <!-- Allows access to TestApis for various components in the biometric stack, including
+ FingerprintService, FaceService, BiometricService. Used by com.android.server.biometrics
+ CTS tests. @hide @TestApi -->
+ <permission android:name="android.permission.TEST_BIOMETRIC"
+ android:protectionLevel="signature" />
+
<!-- Allows direct access to the <Biometric>Service interfaces. Reserved for the system. @hide -->
<permission android:name="android.permission.MANAGE_BIOMETRIC"
android:protectionLevel="signature" />
@@ -4879,6 +4893,11 @@
<permission android:name="android.permission.MANAGE_CONTENT_CAPTURE"
android:protectionLevel="signature" />
+ <!-- @SystemApi Allows an application to manage the music recognition service.
+ @hide <p>Not for use by third-party applications.</p> -->
+ <permission android:name="android.permission.MANAGE_MUSIC_RECOGNITION"
+ android:protectionLevel="signature" />
+
<!-- @SystemApi Allows an application to manage the content suggestions service.
@hide <p>Not for use by third-party applications.</p> -->
<permission android:name="android.permission.MANAGE_CONTENT_SUGGESTIONS"
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index ffc5ff7..b9f0f58 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -327,7 +327,7 @@
<string name="capability_desc_canControlMagnification" msgid="2206586716709254805">"Controla el posicionamiento y el nivel de zoom de la pantalla."</string>
<string name="capability_title_canPerformGestures" msgid="9106545062106728987">"Realizar gestos"</string>
<string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Puedes tocar y pellizcar la pantalla, deslizar el dedo y hacer otros gestos."</string>
- <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Gestos de huellas digitales"</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Gestos de huella digital"</string>
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Puede capturar los gestos realizados en el sensor de huellas digitales del dispositivo."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Hacer captura"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Puede hacer capturas de la pantalla."</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index a99d4d6..907fe5b 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -1658,11 +1658,11 @@
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"کلیدهای میزان صدا پایین نگه داشته شد. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> خاموش شد."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"برای استفاده از <xliff:g id="SERVICE_NAME">%1$s</xliff:g>، هر دو کلید صدا را فشار دهید و سه ثانیه نگه دارید"</string>
<string name="accessibility_button_prompt_text" msgid="8343213623338605305">"ویژگی را انتخاب کنید که هنگام ضربه زدن روی دکمه دسترسپذیری استفاده میشود:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"ویژگی را برای استفاده با اشاره دسترسپذیری انتخاب کنید (با دو انگشت صفحه را از پایین تند به بالا بکشید):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"ویزگی را برای استفاده با اشاره دسترسپذیری انتخاب کنید (با سه انگشت صفحه را از پایین تند به بالا بکشید):"</string>
+ <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"ویژگی را برای استفاده با اشاره دسترسپذیری انتخاب کنید (با دو انگشت صفحه را از پایین تند بهبالا بکشید):"</string>
+ <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"ویزگی را برای استفاده با اشاره دسترسپذیری انتخاب کنید (با سه انگشت صفحه را از پایین تند بهبالا بکشید):"</string>
<string name="accessibility_button_instructional_text" msgid="8853928358872550500">"برای جابهجایی بین ویژگیها، دکمه دسترسپذیری را لمس کنید و نگه دارید."</string>
- <string name="accessibility_gesture_instructional_text" msgid="9196230728837090497">"برای جابهجایی بین ویژگیها، با دو انگشت صفحه را تند به بالا بکشید و نگه دارید."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="3425123684990193765">"برای جابهجایی بین ویژگیها، با سه انگشت صفحه را تند به بالا بکشید و نگه دارید."</string>
+ <string name="accessibility_gesture_instructional_text" msgid="9196230728837090497">"برای جابهجایی بین ویژگیها، با دو انگشت صفحه را تند بهبالا بکشید و نگه دارید."</string>
+ <string name="accessibility_gesture_3finger_instructional_text" msgid="3425123684990193765">"برای جابهجایی بین ویژگیها، با سه انگشت صفحه را تند بهبالا بکشید و نگه دارید."</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"درشتنمایی"</string>
<string name="user_switched" msgid="7249833311585228097">"کاربر کنونی <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="user_switching_message" msgid="1912993630661332336">"در حالت تغییر به <xliff:g id="NAME">%1$s</xliff:g>…"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 59d4d77..d2bdbbb 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -327,7 +327,7 @@
<string name="capability_desc_canControlMagnification" msgid="2206586716709254805">"Contrôle le niveau de zoom et le positionnement de l\'écran."</string>
<string name="capability_title_canPerformGestures" msgid="9106545062106728987">"Effectuer des gestes"</string>
<string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Permet d\'appuyer sur l\'écran, de le balayer, de le pincer et d\'effectuer d\'autres gestes."</string>
- <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Gestes avec l\'empreinte digitale"</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Gestes d\'empreinte digitale"</string>
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Peut enregistrer des gestes effectués sur le lecteur d\'empreinte digitale de l\'appareil."</string>
<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>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index fcf64c1..ffe073c 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -327,7 +327,7 @@
<string name="capability_desc_canControlMagnification" msgid="2206586716709254805">"ഡിസ്പ്ലേയുടെ സൂം നിലയും പൊസിഷനിംഗും നിയന്ത്രിക്കുക."</string>
<string name="capability_title_canPerformGestures" msgid="9106545062106728987">"ജെസ്റ്ററുകൾ നിർവഹിക്കുക"</string>
<string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"ടാപ്പുചെയ്യാനോ സ്വൈപ്പുചെയ്യാനോ പിഞ്ചുചെയ്യാനോ മറ്റ് ജെസ്റ്ററുകൾ നിർവഹിക്കാനോ കഴിയും."</string>
- <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"ഫിംഗർപ്രിന്റ് ജെസ്റ്ററുകൾ"</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"ഫിംഗർപ്രിന്റ് ജെസ്ച്ചറുകൾ"</string>
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"ഉപകരണത്തിന്റെ ഫിംഗർപ്രിന്റ് സെൻസറിൽ ചെയ്ത ജെസ്റ്ററുകൾ ക്യാപ്ചർ ചെയ്യാനാകും."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"സ്ക്രീന്ഷോട്ട് എടുക്കുക"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ഡിസ്പ്ലേയുടെ സ്ക്രീൻഷോട്ട് എടുക്കാൻ കഴിയും."</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 01ee79a9..2cdf709 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -1477,7 +1477,7 @@
<string name="add_account_button_label" msgid="322390749416414097">"खाता थप्नुहोस्"</string>
<string name="number_picker_increment_button" msgid="7621013714795186298">"बढाउनुहोस्"</string>
<string name="number_picker_decrement_button" msgid="5116948444762708204">"घटाउनुहोस्"</string>
- <string name="number_picker_increment_scroll_mode" msgid="8403893549806805985">"<xliff:g id="VALUE">%s</xliff:g> छोइराख्नुहोस्।"</string>
+ <string name="number_picker_increment_scroll_mode" msgid="8403893549806805985">"<xliff:g id="VALUE">%s</xliff:g> टच एण्ड होल्ड गर्नुहोस्।"</string>
<string name="number_picker_increment_scroll_action" msgid="8310191318914268271">"बढाउन माथि र घटाउन तल सार्नुहोस्।"</string>
<string name="time_picker_increment_minute_button" msgid="7195870222945784300">"मिनेट बढाउनुहोस्"</string>
<string name="time_picker_decrement_minute_button" msgid="230925389943411490">"मिनेट घटाउनुहोस्"</string>
@@ -1660,9 +1660,9 @@
<string name="accessibility_button_prompt_text" msgid="8343213623338605305">"तपाईंले पहुँचको बटन ट्याप गर्दा प्रयोग गर्न चाहनुभएको सुविधा छनौट गर्नुहोस्:"</string>
<string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"तपाईंले पहुँचको इसारामार्फत प्रयोग गर्न चाहनुभएको सुविधा छनौट गर्नुहोस् (दुईवटा औँलाले स्क्रिनको फेदबाट माथितिर स्वाइप गर्नुहोस्):"</string>
<string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"तपाईंले पहुँचको इसारामार्फत प्रयोग गर्न चाहनुभएको सुविधा छनौट गर्नुहोस् (तीनवटा औँलाले स्क्रिनको फेदबाट माथितिर स्वाइप गर्नुहोस्):"</string>
- <string name="accessibility_button_instructional_text" msgid="8853928358872550500">"एउटा सुविधाबाट अर्को सुविधामा जान पहुँच बटन छोइराख्नुहोस्।"</string>
- <string name="accessibility_gesture_instructional_text" msgid="9196230728837090497">"एउटा सुविधाबाट अर्को सुविधामा जान दुईवटा औँलाले माथितिर स्वाइप गरी स्क्रिनमा छोइराख्नुहोस्।"</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="3425123684990193765">"एउटा सुविधाबाट अर्को सुविधामा जान तीनवटा औँलाले माथितिर स्वाइप गरी स्क्रिनमा छोइराख्नुहोस्।"</string>
+ <string name="accessibility_button_instructional_text" msgid="8853928358872550500">"एउटा सुविधाबाट अर्को सुविधामा जान पहुँच बटन टच एण्ड होल्ड गर्नुहोस्।"</string>
+ <string name="accessibility_gesture_instructional_text" msgid="9196230728837090497">"एउटा सुविधाबाट अर्को सुविधामा जान दुईवटा औँलाले माथितिर स्वाइप गरी स्क्रिनमा टच एण्ड होल्ड गर्नुहोस्।"</string>
+ <string name="accessibility_gesture_3finger_instructional_text" msgid="3425123684990193765">"एउटा सुविधाबाट अर्को सुविधामा जान तीनवटा औँलाले माथितिर स्वाइप गरी स्क्रिनमा टच एण्ड होल्ड गर्नुहोस्।"</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"म्याग्निफिकेसन"</string>
<string name="user_switched" msgid="7249833311585228097">"अहिलेको प्रयोगकर्ता <xliff:g id="NAME">%1$s</xliff:g>।"</string>
<string name="user_switching_message" msgid="1912993630661332336">"<xliff:g id="NAME">%1$s</xliff:g> मा स्विच गर्दै..."</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 6ea5f52..11bfd78 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -432,23 +432,17 @@
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"ਆਪਣੀਆਂ ਆਡੀਓ ਸੈਟਿੰਗਾਂ ਬਦਲੋ"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"ਐਪ ਨੂੰ ਗਲੋਬਲ ਆਡੀਓ ਸੈਟਿੰਗਾਂ ਸੰਸ਼ੋਧਿਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ ਜਿਵੇਂ ਅਵਾਜ਼ ਅਤੇ ਆਊਟਪੁਟ ਲਈ ਕਿਹੜਾ ਸਪੀਕਰ ਵਰਤਿਆ ਜਾਂਦਾ ਹੈ।"</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">" ਆਡੀਓ ਰਿਕਾਰਡ ਕਰਨ"</string>
- <!-- no translation found for permdesc_recordAudio (5857246765327514062) -->
- <skip />
- <!-- no translation found for permlab_recordBackgroundAudio (5891032812308878254) -->
- <skip />
- <!-- no translation found for permdesc_recordBackgroundAudio (1992623135737407516) -->
- <skip />
+ <string name="permdesc_recordAudio" msgid="5857246765327514062">"ਇਹ ਐਪ ਵਰਤੋਂ ਵਿੱਚ ਹੋਣ ਵੇਲੇ ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਨੂੰ ਵਰਤ ਕੇ ਆਡੀਓ ਰਿਕਾਰਡ ਕਰ ਸਕਦੀ ਹੈ।"</string>
+ <string name="permlab_recordBackgroundAudio" msgid="5891032812308878254">"ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਆਡੀਓ ਰਿਕਾਰਡ ਕਰੋ"</string>
+ <string name="permdesc_recordBackgroundAudio" msgid="1992623135737407516">"ਇਹ ਐਪ ਕਿਸੇ ਵੇਲੇ ਵੀ ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਨੂੰ ਵਰਤ ਕੇ ਆਡੀਓ ਰਿਕਾਰਡ ਕਰ ਸਕਦੀ ਹੈ।"</string>
<string name="permlab_sim_communication" msgid="176788115994050692">"SIM ਨੂੰ ਕਮਾਂਡਾਂ ਭੇਜੋ"</string>
<string name="permdesc_sim_communication" msgid="4179799296415957960">"ਐਪ ਨੂੰ SIM ਨੂੰ ਕਮਾਂਡਾਂ ਭੇਜਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਹ ਬਹੁਤ ਘਾਤਕ ਹੈ।"</string>
<string name="permlab_activityRecognition" msgid="1782303296053990884">"ਸਰੀਰਕ ਸਰਗਰਮੀ ਨੂੰ ਪਛਾਣਨਾ"</string>
<string name="permdesc_activityRecognition" msgid="8667484762991357519">"ਇਹ ਐਪ ਤੁਹਾਡੀ ਸਰੀਰਕ ਸਰਗਰਮੀ ਨੂੰ ਪਛਾਣ ਸਕਦੀ ਹੈ।"</string>
<string name="permlab_camera" msgid="6320282492904119413">"ਤਸਵੀਰਾਂ ਅਤੇ ਵੀਡੀਓ ਬਣਾਓ"</string>
- <!-- no translation found for permdesc_camera (5240801376168647151) -->
- <skip />
- <!-- no translation found for permlab_backgroundCamera (7549917926079731681) -->
- <skip />
- <!-- no translation found for permdesc_backgroundCamera (1615291686191138250) -->
- <skip />
+ <string name="permdesc_camera" msgid="5240801376168647151">"ਇਹ ਐਪ ਵਰਤੋਂ ਵਿੱਚ ਹੋਣ ਵੇਲੇ ਕੈਮਰੇ ਨੂੰ ਵਰਤ ਕੇ ਤਸਵੀਰਾਂ ਖਿੱਚ ਸਕਦੀ ਹੈ ਅਤੇ ਵੀਡੀਓ ਰਿਕਾਰਡ ਕਰ ਸਕਦੀ ਹੈ।"</string>
+ <string name="permlab_backgroundCamera" msgid="7549917926079731681">"ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਤਸਵੀਰਾਂ ਖਿੱਚੋ ਅਤੇ ਵੀਡੀਓ ਰਿਕਾਰਡ ਕਰੋ"</string>
+ <string name="permdesc_backgroundCamera" msgid="1615291686191138250">"ਇਹ ਐਪ ਕਿਸੇ ਵੇਲੇ ਵੀ ਕੈਮਰੇ ਨੂੰ ਵਰਤ ਕੇ ਤਸਵੀਰਾਂ ਖਿੱਚ ਸਕਦੀ ਹੈ ਅਤੇ ਵੀਡੀਓ ਰਿਕਾਰਡ ਕਰ ਸਕਦੀ ਹੈ।"</string>
<string name="permlab_systemCamera" msgid="3642917457796210580">"ਸਿਸਟਮ ਕੈਮਰੇ ਨੂੰ ਤਸਵੀਰਾਂ ਅਤੇ ਵੀਡੀਓ ਬਣਾਉਣ ਲਈ ਐਪਲੀਕੇਸ਼ਨ ਜਾਂ ਸੇਵਾ ਤੱਕ ਪਹੁੰਚ ਦਿਓ"</string>
<string name="permdesc_systemCamera" msgid="5938360914419175986">"ਇਹ ਵਿਸ਼ੇਸ਼ ਅਧਿਕ੍ਰਿਤ ਜਾਂ ਸਿਸਟਮ ਐਪ ਕਿਸੇ ਵੇਲੇ ਵੀ ਸਿਸਟਮ ਕੈਮਰੇ ਨੂੰ ਵਰਤ ਕੇ ਤਸਵੀਰਾਂ ਖਿੱਚ ਸਕਦੀ ਹੈ ਅਤੇ ਵੀਡੀਓ ਫ਼ਾਈਲਾਂ ਰਿਕਾਰਡ ਕਰ ਸਕਦੀ ਹੈ। ਐਪ ਨੂੰ ਵੀ android.permission.CAMERA ਇਜਾਜ਼ਤ ਦੀ ਲੋੜ ਹੈ"</string>
<string name="permlab_cameraOpenCloseListener" msgid="5548732769068109315">"ਐਪਲੀਕੇਸ਼ਨ ਜਾਂ ਸੇਵਾ ਨੂੰ ਕੈਮਰਾ ਡੀਵਾਈਸਾਂ ਦੇ ਚਾਲੂ ਜਾਂ ਬੰਦ ਕੀਤੇ ਜਾਣ ਬਾਰੇ ਕਾਲਬੈਕ ਪ੍ਰਾਪਤ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਦਿਓ।"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 0c15f9e..da41508 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1137,7 +1137,7 @@
<string name="elapsed_time_short_format_mm_ss" msgid="8689459651807876423">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string>
<string name="elapsed_time_short_format_h_mm_ss" msgid="2302144714803345056">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string>
<string name="selectAll" msgid="1532369154488982046">"Вибрати все"</string>
- <string name="cut" msgid="2561199725874745819">"Виріз."</string>
+ <string name="cut" msgid="2561199725874745819">"Вирізати"</string>
<string name="copy" msgid="5472512047143665218">"Копіювати"</string>
<string name="failed_to_copy_to_clipboard" msgid="725919885138539875">"Не вдалося скопіювати в буфер обміну"</string>
<string name="paste" msgid="461843306215520225">"Вставити"</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 0cfbf6d..e434ac9 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3660,6 +3660,8 @@
-->
<string name="config_defaultContentSuggestionsService" translatable="false"></string>
+ <string name="config_defaultMusicRecognitionService" translatable="false"></string>
+
<!-- The package name for the default retail demo app.
This package must be trusted, as it has the permissions to query the usage stats on the
device.
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 6009689..1249b17 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3454,6 +3454,7 @@
<java-symbol type="string" name="config_defaultAugmentedAutofillService" />
<java-symbol type="string" name="config_defaultAppPredictionService" />
<java-symbol type="string" name="config_defaultContentSuggestionsService" />
+ <java-symbol type="string" name="config_defaultMusicRecognitionService" />
<java-symbol type="string" name="config_defaultAttentionService" />
<java-symbol type="string" name="config_defaultSystemCaptionsService" />
<java-symbol type="string" name="config_defaultSystemCaptionsManagerService" />
diff --git a/core/tests/coretests/src/com/android/internal/view/RecyclerViewCaptureHelperTest.java b/core/tests/coretests/src/com/android/internal/view/RecyclerViewCaptureHelperTest.java
new file mode 100644
index 0000000..88bbcc2
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/view/RecyclerViewCaptureHelperTest.java
@@ -0,0 +1,343 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.view;
+
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.fail;
+
+import android.app.Instrumentation;
+import android.content.Context;
+import android.graphics.Color;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.widget.FrameLayout;
+import android.widget.TextView;
+
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.internal.view.ScrollCaptureViewHelper.ScrollResult;
+import com.android.internal.widget.LinearLayoutManager;
+import com.android.internal.widget.RecyclerView;
+
+import com.google.common.truth.Truth;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Random;
+
+@RunWith(AndroidJUnit4.class)
+public class RecyclerViewCaptureHelperTest {
+ private static final int CHILD_VIEWS = 12;
+ private static final int CHILD_VIEW_HEIGHT = 300;
+ private static final int WINDOW_WIDTH = 800;
+ private static final int WINDOW_HEIGHT = 1200;
+ private static final int CAPTURE_HEIGHT = 600;
+
+ private FrameLayout mParent;
+ private RecyclerView mTarget;
+ private WindowManager mWm;
+
+ private WindowManager.LayoutParams mWindowLayoutParams;
+
+ private Context mContext;
+ private float mDensity;
+ private LinearLayoutManager mLinearLayoutManager;
+ private Instrumentation mInstrumentation;
+
+ @Before
+ @UiThreadTest
+ public void setUp() {
+ mInstrumentation = InstrumentationRegistry.getInstrumentation();
+ mContext = mInstrumentation.getContext();
+ mDensity = mContext.getResources().getDisplayMetrics().density;
+
+ mParent = new FrameLayout(mContext);
+
+ mTarget = new RecyclerView(mContext);
+ mParent.addView(mTarget, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
+
+ mTarget.setAdapter(new TestAdapter());
+ mLinearLayoutManager =
+ new LinearLayoutManager(mContext, LinearLayoutManager.VERTICAL, false);
+ mTarget.setLayoutManager(mLinearLayoutManager);
+ mWm = mContext.getSystemService(WindowManager.class);
+
+ // Setup the window that we are going to use
+ mWindowLayoutParams = new WindowManager.LayoutParams(WINDOW_WIDTH, WINDOW_HEIGHT,
+ TYPE_APPLICATION_OVERLAY, FLAG_NOT_TOUCHABLE, PixelFormat.OPAQUE);
+ mWindowLayoutParams.setTitle("ScrollViewCaptureHelper");
+ mWindowLayoutParams.gravity = Gravity.CENTER;
+ mWm.addView(mParent, mWindowLayoutParams);
+ }
+
+ @After
+ @UiThreadTest
+ public void tearDown() {
+ mWm.removeViewImmediate(mParent);
+ }
+
+ @Test
+ @UiThreadTest
+ public void onScrollRequested_up_fromTop() {
+ mTarget.scrollBy(0, -(WINDOW_HEIGHT * 3));
+ // mTarget.createSnapshot(new ViewDebug.HardwareCanvasProvider(), false);
+
+ RecyclerViewCaptureHelper rvc = new RecyclerViewCaptureHelper();
+ Rect scrollBounds = rvc.onComputeScrollBounds(mTarget);
+ rvc.onPrepareForStart(mTarget, scrollBounds);
+
+ assertThat(scrollBounds.height()).isGreaterThan(CAPTURE_HEIGHT);
+
+ Rect request = new Rect(0, -CAPTURE_HEIGHT, scrollBounds.width(), 0);
+
+ ScrollResult scrollResult = rvc.onScrollRequested(mTarget,
+ scrollBounds, request);
+
+ // The result is an empty rectangle and no scrolling, since it
+ // is not possible to physically scroll further up to make the
+ // requested area visible at all (it doesn't exist).
+ assertEmpty(scrollResult.availableArea);
+ }
+
+ @Test
+ @UiThreadTest
+ public void onScrollRequested_down_fromTop() {
+ mTarget.scrollBy(0, -(WINDOW_HEIGHT * 3));
+
+ RecyclerViewCaptureHelper rvc = new RecyclerViewCaptureHelper();
+ Rect scrollBounds = rvc.onComputeScrollBounds(mTarget);
+ rvc.onPrepareForStart(mTarget, scrollBounds);
+
+ assertThat(scrollBounds.height()).isGreaterThan(CAPTURE_HEIGHT);
+
+ // Capture between y = +1200 to +1800 pixels BELOW current top
+ Rect request = new Rect(0, WINDOW_HEIGHT, scrollBounds.width(),
+ WINDOW_HEIGHT + CAPTURE_HEIGHT);
+
+ ScrollResult scrollResult = rvc.onScrollRequested(mTarget, scrollBounds, request);
+ assertThat(request).isEqualTo(scrollResult.requestedArea);
+ assertThat(request).isEqualTo(scrollResult.availableArea);
+ assertThat(scrollResult.scrollDelta).isEqualTo(CAPTURE_HEIGHT);
+ assertAvailableAreaCompletelyVisible(scrollResult, mTarget);
+ }
+
+ @Test
+ @UiThreadTest
+ public void onScrollRequested_up_fromMiddle() {
+ mTarget.scrollBy(0, WINDOW_HEIGHT);
+
+ RecyclerViewCaptureHelper helper = new RecyclerViewCaptureHelper();
+ Rect scrollBounds = helper.onComputeScrollBounds(mTarget);
+ helper.onPrepareForStart(mTarget, scrollBounds);
+
+ Rect request = new Rect(0, -CAPTURE_HEIGHT, scrollBounds.width(), 0);
+
+ ScrollResult scrollResult = helper.onScrollRequested(mTarget, scrollBounds, request);
+ assertThat(request).isEqualTo(scrollResult.requestedArea);
+ assertThat(request).isEqualTo(scrollResult.availableArea);
+ assertThat(scrollResult.scrollDelta).isEqualTo(-CAPTURE_HEIGHT);
+ assertAvailableAreaCompletelyVisible(scrollResult, mTarget);
+ }
+
+ @Test
+ @UiThreadTest
+ public void onScrollRequested_down_fromMiddle() {
+ mTarget.scrollBy(0, WINDOW_HEIGHT);
+
+ RecyclerViewCaptureHelper helper = new RecyclerViewCaptureHelper();
+ Rect scrollBounds = helper.onComputeScrollBounds(mTarget);
+ helper.onPrepareForStart(mTarget, scrollBounds);
+
+ Rect request = new Rect(0, WINDOW_HEIGHT, scrollBounds.width(),
+ WINDOW_HEIGHT + CAPTURE_HEIGHT);
+
+ ScrollResult scrollResult = helper.onScrollRequested(mTarget, scrollBounds, request);
+ assertThat(request).isEqualTo(scrollResult.requestedArea);
+ assertThat(request).isEqualTo(scrollResult.availableArea);
+ assertThat(scrollResult.scrollDelta).isEqualTo(CAPTURE_HEIGHT);
+ assertAvailableAreaCompletelyVisible(scrollResult, mTarget);
+ }
+
+ @Test
+ @UiThreadTest
+ public void onScrollRequested_up_fromBottom() {
+ mTarget.scrollBy(0, WINDOW_HEIGHT * 2);
+
+ RecyclerViewCaptureHelper helper = new RecyclerViewCaptureHelper();
+ Rect scrollBounds = helper.onComputeScrollBounds(mTarget);
+ helper.onPrepareForStart(mTarget, scrollBounds);
+
+ Rect request = new Rect(0, -CAPTURE_HEIGHT, scrollBounds.width(), 0);
+
+ ScrollResult scrollResult = helper.onScrollRequested(mTarget, scrollBounds, request);
+ assertThat(request).isEqualTo(scrollResult.requestedArea);
+ assertThat(request).isEqualTo(scrollResult.availableArea);
+ assertThat(scrollResult.scrollDelta).isEqualTo(-CAPTURE_HEIGHT);
+ assertAvailableAreaCompletelyVisible(scrollResult, mTarget);
+ }
+
+ @Test
+ @UiThreadTest
+ public void onScrollRequested_down_fromBottom() {
+ mTarget.scrollBy(0, WINDOW_HEIGHT * 3);
+
+ RecyclerViewCaptureHelper rvc = new RecyclerViewCaptureHelper();
+ Rect scrollBounds = rvc.onComputeScrollBounds(mTarget);
+ rvc.onPrepareForStart(mTarget, scrollBounds);
+
+ Rect request = new Rect(0, WINDOW_HEIGHT, scrollBounds.width(),
+ WINDOW_HEIGHT + CAPTURE_HEIGHT);
+
+ ScrollResult scrollResult = rvc.onScrollRequested(mTarget,
+ scrollBounds, request);
+ Truth.assertThat(request).isEqualTo(scrollResult.requestedArea);
+
+ // The result is an empty rectangle and no scrolling, since it
+ // is not possible to physically scroll further down to make the
+ // requested area visible at all (it doesn't exist).
+ assertEmpty(scrollResult.availableArea);
+ }
+
+ @Test
+ @UiThreadTest
+ public void onScrollRequested_offTopEdge() {
+ mTarget.scrollBy(0, -(WINDOW_HEIGHT * 3));
+
+ RecyclerViewCaptureHelper helper = new RecyclerViewCaptureHelper();
+ Rect scrollBounds = helper.onComputeScrollBounds(mTarget);
+ helper.onPrepareForStart(mTarget, scrollBounds);
+
+ // Create a request which lands halfway off the top of the content
+ //from -1500 to -900, (starting at 1200 = -300 to +300 within the content)
+ int top = 0;
+ Rect request = new Rect(
+ 0, top - (CAPTURE_HEIGHT / 2),
+ scrollBounds.width(), top + (CAPTURE_HEIGHT / 2));
+
+ ScrollResult scrollResult = helper.onScrollRequested(mTarget, scrollBounds, request);
+ assertThat(request).isEqualTo(scrollResult.requestedArea);
+
+ ScrollResult result = helper.onScrollRequested(mTarget, scrollBounds, request);
+ // The result is a partial result
+ Rect expectedResult = new Rect(request);
+ expectedResult.top += (CAPTURE_HEIGHT / 2); // top half clipped
+ assertThat(expectedResult).isEqualTo(result.availableArea);
+ assertThat(scrollResult.scrollDelta).isEqualTo(0);
+ assertAvailableAreaPartiallyVisible(scrollResult, mTarget);
+ }
+
+ @Test
+ @UiThreadTest
+ public void onScrollRequested_offBottomEdge() {
+ mTarget.scrollBy(0, WINDOW_HEIGHT * 2);
+
+ RecyclerViewCaptureHelper helper = new RecyclerViewCaptureHelper();
+ Rect scrollBounds = helper.onComputeScrollBounds(mTarget);
+ helper.onPrepareForStart(mTarget, scrollBounds);
+
+ // Create a request which lands halfway off the bottom of the content
+ //from 600 to to 1200, (starting at 2400 = 3000 to 3600 within the content)
+
+ int bottom = WINDOW_HEIGHT;
+ Rect request = new Rect(
+ 0, bottom - (CAPTURE_HEIGHT / 2),
+ scrollBounds.width(), bottom + (CAPTURE_HEIGHT / 2));
+
+ ScrollResult result = helper.onScrollRequested(mTarget, scrollBounds, request);
+
+ Rect expectedResult = new Rect(request);
+ expectedResult.bottom -= 300; // bottom half clipped
+ assertThat(expectedResult).isEqualTo(result.availableArea);
+ assertThat(result.scrollDelta).isEqualTo(0);
+ assertAvailableAreaPartiallyVisible(result, mTarget);
+ }
+
+ static final class TestViewHolder extends RecyclerView.ViewHolder {
+ TestViewHolder(View itemView) {
+ super(itemView);
+ }
+ }
+
+ static final class TestAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
+ private final Random mRandom = new Random();
+
+ @Override
+ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ return new TestViewHolder(new TextView(parent.getContext()));
+ }
+
+ @Override
+ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
+ TextView view = (TextView) holder.itemView;
+ view.setText("Child #" + position);
+ view.setTextColor(Color.WHITE);
+ view.setTextSize(30f);
+ view.setBackgroundColor(Color.rgb(mRandom.nextFloat(), mRandom.nextFloat(),
+ mRandom.nextFloat()));
+ view.setMinHeight(CHILD_VIEW_HEIGHT);
+ }
+
+ @Override
+ public int getItemCount() {
+ return CHILD_VIEWS;
+ }
+ }
+
+ static void assertEmpty(Rect r) {
+ if (r != null && !r.isEmpty()) {
+ fail("Not true that " + r + " is empty");
+ }
+ }
+
+ static Rect getVisibleRect(View v) {
+ Rect r = new Rect(0, 0, v.getWidth(), v.getHeight());
+ v.getLocalVisibleRect(r);
+ return r;
+ }
+
+ static void assertAvailableAreaCompletelyVisible(ScrollResult result, View container) {
+ Rect requested = new Rect(result.availableArea);
+ requested.offset(0, -result.scrollDelta); // make relative
+ Rect localVisible = getVisibleRect(container);
+ if (!localVisible.contains(requested)) {
+ fail("Not true that all of " + requested + " is contained by " + localVisible);
+ }
+ }
+
+ static void assertAvailableAreaPartiallyVisible(ScrollResult result, View container) {
+ Rect requested = new Rect(result.availableArea);
+ requested.offset(0, -result.scrollDelta); // make relative
+ Rect localVisible = getVisibleRect(container);
+ if (!Rect.intersects(localVisible, requested)) {
+ fail("Not true that any of " + requested + " is contained by " + localVisible);
+ }
+ }
+}
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 81da5c8..4c3b36f 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -437,6 +437,9 @@
<permission name="android.permission.MANAGE_DEBUGGING" />
<!-- Permissions required for CTS test - TimeManagerTest -->
<permission name="android.permission.MANAGE_TIME_AND_ZONE_DETECTION" />
+ <!-- Permissions required for CTS test - android.server.biometrics -->
+ <permission name="android.permission.USE_BIOMETRIC" />
+ <permission name="android.permission.TEST_BIOMETRIC" />
</privapp-permissions>
<privapp-permissions package="com.android.statementservice">
diff --git a/graphics/java/android/graphics/ParcelableColorSpace.java b/graphics/java/android/graphics/ParcelableColorSpace.java
index d408ac3..3260849 100644
--- a/graphics/java/android/graphics/ParcelableColorSpace.java
+++ b/graphics/java/android/graphics/ParcelableColorSpace.java
@@ -73,6 +73,9 @@
}
}
+ /**
+ * @return the backing ColorSpace that this ParcelableColorSpace is wrapping.
+ */
public @NonNull ColorSpace getColorSpace() {
return mColorSpace;
}
diff --git a/graphics/java/android/graphics/RuntimeShader.java b/graphics/java/android/graphics/RuntimeShader.java
index 5a0b4a9..63089e2 100644
--- a/graphics/java/android/graphics/RuntimeShader.java
+++ b/graphics/java/android/graphics/RuntimeShader.java
@@ -34,6 +34,7 @@
}
private byte[] mUniforms;
+ private Shader[] mInputShaders;
private boolean mIsOpaque;
/**
@@ -50,13 +51,30 @@
* @param isOpaque True if all pixels have alpha 1.0f.
*/
public RuntimeShader(@NonNull String sksl, @Nullable byte[] uniforms, boolean isOpaque) {
- this(sksl, uniforms, isOpaque, ColorSpace.get(ColorSpace.Named.SRGB));
+ this(sksl, uniforms, null, isOpaque, ColorSpace.get(ColorSpace.Named.SRGB));
}
- private RuntimeShader(@NonNull String sksl, @Nullable byte[] uniforms, boolean isOpaque,
- ColorSpace colorSpace) {
+ /**
+ * Creates a new RuntimeShader.
+ *
+ * @param sksl The text of SKSL program to run on the GPU.
+ * @param uniforms Array of parameters passed by the SKSL shader. Array size depends
+ * on number of uniforms declared by sksl.
+ * @param shaderInputs Array of shaders passed to the SKSL shader. Array size depends
+ * on the number of input shaders declared in the sksl
+ * @param isOpaque True if all pixels have alpha 1.0f.
+ */
+ public RuntimeShader(@NonNull String sksl, @Nullable byte[] uniforms,
+ @Nullable Shader[] shaderInputs, boolean isOpaque) {
+ this(sksl, uniforms, shaderInputs, isOpaque, ColorSpace.get(ColorSpace.Named.SRGB));
+ }
+
+ private RuntimeShader(@NonNull String sksl, @Nullable byte[] uniforms,
+ @Nullable Shader[] shaderInputs, boolean isOpaque,
+ ColorSpace colorSpace) {
super(colorSpace);
mUniforms = uniforms;
+ mInputShaders = shaderInputs;
mIsOpaque = isOpaque;
mNativeInstanceRuntimeShaderFactory = nativeCreateShaderFactory(sksl);
NoImagePreloadHolder.sRegistry.registerNativeAllocation(this,
@@ -74,15 +92,31 @@
discardNativeInstance();
}
+ /**
+ * Sets new values for the shaders that serve as inputs to this shader.
+ *
+ * @param shaderInputs Array of Shaders passed into the SKSL shader. Array size depends
+ * on number of input shaders declared by sksl.
+ */
+ public void updateInputShaders(@Nullable Shader[] shaderInputs) {
+ mInputShaders = shaderInputs;
+ discardNativeInstance();
+ }
+
/** @hide */
@Override
protected long createNativeInstance(long nativeMatrix) {
+ long[] nativeShaders = mInputShaders.length > 0 ? new long[mInputShaders.length] : null;
+ for (int i = 0; i < mInputShaders.length; i++) {
+ nativeShaders[i] = mInputShaders[i].getNativeInstance();
+ }
+
return nativeCreate(mNativeInstanceRuntimeShaderFactory, nativeMatrix, mUniforms,
- colorSpace().getNativeInstance(), mIsOpaque);
+ nativeShaders, colorSpace().getNativeInstance(), mIsOpaque);
}
private static native long nativeCreate(long shaderFactory, long matrix, byte[] inputs,
- long colorSpaceHandle, boolean isOpaque);
+ long[] shaderInputs, long colorSpaceHandle, boolean isOpaque);
private static native long nativeCreateShaderFactory(String sksl);
diff --git a/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json b/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json
index 227eec2..bcef154 100644
--- a/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json
+++ b/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json
@@ -1,6 +1,12 @@
{
"version": "1.0.0",
"messages": {
+ "-1823823103": {
+ "message": "Add listener for types=%s listener=%s",
+ "level": "VERBOSE",
+ "group": "WM_SHELL_TASK_ORG",
+ "at": "com\/android\/wm\/shell\/ShellTaskOrganizer.java"
+ },
"-1534364071": {
"message": "onTransitionReady %s: %s",
"level": "VERBOSE",
@@ -37,12 +43,6 @@
"group": "WM_SHELL_TASK_ORG",
"at": "com\/android\/wm\/shell\/ShellTaskOrganizer.java"
},
- "-242812822": {
- "message": "Add listener for modes=%s listener=%s",
- "level": "VERBOSE",
- "group": "WM_SHELL_TASK_ORG",
- "at": "com\/android\/wm\/shell\/ShellTaskOrganizer.java"
- },
"-191422040": {
"message": "Transition animations finished, notifying core %s",
"level": "VERBOSE",
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
index 4f610efd..7ce65fd 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
@@ -16,9 +16,17 @@
package com.android.wm.shell;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import android.annotation.IntDef;
import android.app.ActivityManager.RunningTaskInfo;
+import android.app.WindowConfiguration.WindowingMode;
import android.util.Log;
import android.util.Pair;
import android.util.SparseArray;
@@ -33,7 +41,6 @@
import com.android.wm.shell.common.TransactionPool;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
-import java.util.ArrayList;
import java.util.Arrays;
/**
@@ -42,6 +49,23 @@
*/
public class ShellTaskOrganizer extends TaskOrganizer {
+ // Intentionally using negative numbers here so the positive numbers can be used
+ // for task id specific listeners that will be added later.
+ public static final int TASK_LISTENER_TYPE_UNDEFINED = -1;
+ public static final int TASK_LISTENER_TYPE_FULLSCREEN = -2;
+ public static final int TASK_LISTENER_TYPE_MULTI_WINDOW = -3;
+ public static final int TASK_LISTENER_TYPE_PIP = -4;
+ public static final int TASK_LISTENER_TYPE_SPLIT_SCREEN = -5;
+
+ @IntDef(prefix = {"TASK_LISTENER_TYPE_"}, value = {
+ TASK_LISTENER_TYPE_UNDEFINED,
+ TASK_LISTENER_TYPE_FULLSCREEN,
+ TASK_LISTENER_TYPE_MULTI_WINDOW,
+ TASK_LISTENER_TYPE_PIP,
+ TASK_LISTENER_TYPE_SPLIT_SCREEN,
+ })
+ public @interface TaskListenerType {}
+
private static final String TAG = "ShellTaskOrganizer";
/**
@@ -54,7 +78,7 @@
default void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) {}
}
- private final SparseArray<TaskListener> mListenerByWindowingMode = new SparseArray<>();
+ private final SparseArray<TaskListener> mTaskListenersByType = new SparseArray<>();
// Keeps track of all the tasks reported to this organizer (changes in windowing mode will
// require us to report to both old and new listeners)
@@ -73,29 +97,29 @@
SyncTransactionQueue syncQueue, TransactionPool transactionPool,
ShellExecutor mainExecutor, ShellExecutor animExecutor) {
super(taskOrganizerController);
- addListener(new FullscreenTaskListener(syncQueue), WINDOWING_MODE_FULLSCREEN);
+ addListener(new FullscreenTaskListener(syncQueue), TASK_LISTENER_TYPE_FULLSCREEN);
mTransitions = new Transitions(this, transactionPool, mainExecutor, animExecutor);
if (Transitions.ENABLE_SHELL_TRANSITIONS) registerTransitionPlayer(mTransitions);
}
/**
- * Adds a listener for tasks in a specific windowing mode.
+ * Adds a listener for tasks with given types.
*/
- public void addListener(TaskListener listener, int... windowingModes) {
- ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Add listener for modes=%s listener=%s",
- Arrays.toString(windowingModes), listener);
- for (int winMode : windowingModes) {
- if (mListenerByWindowingMode.get(winMode) != null) {
- throw new IllegalArgumentException("Listener for winMode=" + winMode
+ public void addListener(TaskListener listener, @TaskListenerType int... taskListenerTypes) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Add listener for types=%s listener=%s",
+ Arrays.toString(taskListenerTypes), listener);
+ for (int listenerType : taskListenerTypes) {
+ if (mTaskListenersByType.get(listenerType) != null) {
+ throw new IllegalArgumentException("Listener for listenerType=" + listenerType
+ " already exists");
}
- mListenerByWindowingMode.put(winMode, listener);
+ mTaskListenersByType.put(listenerType, listener);
- // Notify the listener of all existing tasks in that windowing mode
+ // Notify the listener of all existing tasks with the given type.
for (int i = mTasks.size() - 1; i >= 0; i--) {
Pair<RunningTaskInfo, SurfaceControl> data = mTasks.valueAt(i);
- int taskWinMode = data.first.configuration.windowConfiguration.getWindowingMode();
- if (taskWinMode == winMode) {
+ final @TaskListenerType int taskListenerType = getTaskListenerType(data.first);
+ if (taskListenerType == listenerType) {
listener.onTaskAppeared(data.first, data.second);
}
}
@@ -107,12 +131,12 @@
*/
public void removeListener(TaskListener listener) {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Remove listener=%s", listener);
- final int index = mListenerByWindowingMode.indexOfValue(listener);
+ final int index = mTaskListenersByType.indexOfValue(listener);
if (index == -1) {
Log.w(TAG, "No registered listener found");
return;
}
- mListenerByWindowingMode.removeAt(index);
+ mTaskListenersByType.removeAt(index);
}
@Override
@@ -120,7 +144,7 @@
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Task appeared taskId=%d",
taskInfo.taskId);
mTasks.put(taskInfo.taskId, new Pair<>(taskInfo, leash));
- final TaskListener listener = mListenerByWindowingMode.get(getWindowingMode(taskInfo));
+ final TaskListener listener = mTaskListenersByType.get(getTaskListenerType(taskInfo));
if (listener != null) {
listener.onTaskAppeared(taskInfo, leash);
}
@@ -131,23 +155,23 @@
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Task info changed taskId=%d",
taskInfo.taskId);
final Pair<RunningTaskInfo, SurfaceControl> data = mTasks.get(taskInfo.taskId);
- final int winMode = getWindowingMode(taskInfo);
- final int prevWinMode = getWindowingMode(data.first);
+ final @TaskListenerType int listenerType = getTaskListenerType(taskInfo);
+ final @TaskListenerType int prevListenerType = getTaskListenerType(data.first);
mTasks.put(taskInfo.taskId, new Pair<>(taskInfo, data.second));
- if (prevWinMode != -1 && prevWinMode != winMode) {
- // TODO: We currently send vanished/appeared as the task moves between win modes, but
+ if (prevListenerType != listenerType) {
+ // TODO: We currently send vanished/appeared as the task moves between types, but
// we should consider adding a different mode-changed callback
- TaskListener listener = mListenerByWindowingMode.get(prevWinMode);
+ TaskListener listener = mTaskListenersByType.get(prevListenerType);
if (listener != null) {
listener.onTaskVanished(taskInfo);
}
- listener = mListenerByWindowingMode.get(winMode);
+ listener = mTaskListenersByType.get(listenerType);
if (listener != null) {
SurfaceControl leash = data.second;
listener.onTaskAppeared(taskInfo, leash);
}
} else {
- final TaskListener listener = mListenerByWindowingMode.get(winMode);
+ final TaskListener listener = mTaskListenersByType.get(listenerType);
if (listener != null) {
listener.onTaskInfoChanged(taskInfo);
}
@@ -158,7 +182,7 @@
public void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Task root back pressed taskId=%d",
taskInfo.taskId);
- final TaskListener listener = mListenerByWindowingMode.get(getWindowingMode(taskInfo));
+ final TaskListener listener = mTaskListenersByType.get(getTaskListenerType(taskInfo));
if (listener != null) {
listener.onBackPressedOnTaskRoot(taskInfo);
}
@@ -168,15 +192,38 @@
public void onTaskVanished(RunningTaskInfo taskInfo) {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Task vanished taskId=%d",
taskInfo.taskId);
- final int prevWinMode = getWindowingMode(mTasks.get(taskInfo.taskId).first);
+ final @TaskListenerType int prevListenerType =
+ getTaskListenerType(mTasks.get(taskInfo.taskId).first);
mTasks.remove(taskInfo.taskId);
- final TaskListener listener = mListenerByWindowingMode.get(prevWinMode);
+ final TaskListener listener = mTaskListenersByType.get(prevListenerType);
if (listener != null) {
listener.onTaskVanished(taskInfo);
}
}
- private int getWindowingMode(RunningTaskInfo taskInfo) {
+ @TaskListenerType
+ private static int getTaskListenerType(RunningTaskInfo runningTaskInfo) {
+ // Right now it's N:1 mapping but in the future different task listerners
+ // may be triggered by one windowing mode depending on task parameters.
+ switch (getWindowingMode(runningTaskInfo)) {
+ case WINDOWING_MODE_FULLSCREEN:
+ return TASK_LISTENER_TYPE_FULLSCREEN;
+ case WINDOWING_MODE_MULTI_WINDOW:
+ return TASK_LISTENER_TYPE_MULTI_WINDOW;
+ case WINDOWING_MODE_SPLIT_SCREEN_PRIMARY:
+ case WINDOWING_MODE_SPLIT_SCREEN_SECONDARY:
+ return TASK_LISTENER_TYPE_SPLIT_SCREEN;
+ case WINDOWING_MODE_PINNED:
+ return TASK_LISTENER_TYPE_PIP;
+ case WINDOWING_MODE_FREEFORM:
+ case WINDOWING_MODE_UNDEFINED:
+ default:
+ return TASK_LISTENER_TYPE_UNDEFINED;
+ }
+ }
+
+ @WindowingMode
+ private static int getWindowingMode(RunningTaskInfo taskInfo) {
return taskInfo.configuration.windowConfiguration.getWindowingMode();
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
index 05877d4..846da0a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
@@ -21,6 +21,7 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_PIP;
import static com.android.wm.shell.pip.PipAnimationController.ANIM_TYPE_ALPHA;
import static com.android.wm.shell.pip.PipAnimationController.ANIM_TYPE_BOUNDS;
import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_LEAVE_PIP;
@@ -282,7 +283,7 @@
if (!PipUtils.hasSystemFeature(context)) {
Log.w(TAG, "Device not support PIP feature");
} else {
- mTaskOrganizer.addListener(this, WINDOWING_MODE_PINNED);
+ mTaskOrganizer.addListener(this, TASK_LISTENER_TYPE_PIP);
displayController.addDisplayWindowListener(this);
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
index 41c0a88..ea9c960 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
@@ -61,7 +61,6 @@
private final DisplayInfo mTmpDisplayInfo = new DisplayInfo();
private final Rect mTmpInsetBounds = new Rect();
private final Rect mTmpNormalBounds = new Rect();
- protected final Rect mReentryBounds = new Rect();
private DisplayController mDisplayController;
private PipAppOpsListener mAppOpsListener;
@@ -396,8 +395,7 @@
public void onPipTransitionStarted(ComponentName activity, int direction, Rect pipBounds) {
if (isOutPipDirection(direction)) {
// Exiting PIP, save the reentry bounds to restore to when re-entering.
- updateReentryBounds(pipBounds);
- mPipBoundsHandler.onSaveReentryBounds(activity, mReentryBounds);
+ mPipBoundsHandler.onSaveReentryBounds(activity, pipBounds);
}
// Disable touches while the animation is running
mTouchHandler.setTouchEnabled(false);
@@ -406,16 +404,6 @@
}
}
- /**
- * Update the bounds used to save the re-entry size and snap fraction when exiting PIP.
- */
- public void updateReentryBounds(Rect bounds) {
- final Rect reentryBounds = mTouchHandler.getUserResizeBounds();
- float snapFraction = mPipBoundsHandler.getSnapFraction(bounds);
- mPipBoundsHandler.applySnapFraction(reentryBounds, snapFraction);
- mReentryBounds.set(reentryBounds);
- }
-
@Override
public void onPipTransitionFinished(ComponentName activity, int direction) {
onPipTransitionFinishedOrCanceled(direction);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskOrganizer.java
index 30bc43b..8660702 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskOrganizer.java
@@ -23,8 +23,9 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.view.Display.DEFAULT_DISPLAY;
+import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_SPLIT_SCREEN;
+
import android.app.ActivityManager.RunningTaskInfo;
-import android.app.WindowConfiguration;
import android.graphics.Rect;
import android.os.RemoteException;
import android.util.Log;
@@ -56,17 +57,16 @@
ShellTaskOrganizer shellTaskOrganizer) {
mSplitScreenController = splitScreenController;
mTaskOrganizer = shellTaskOrganizer;
- mTaskOrganizer.addListener(this, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY,
- WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
+ mTaskOrganizer.addListener(this, TASK_LISTENER_TYPE_SPLIT_SCREEN);
}
void init() throws RemoteException {
synchronized (this) {
try {
mPrimary = mTaskOrganizer.createRootTask(Display.DEFAULT_DISPLAY,
- WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
+ WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
mSecondary = mTaskOrganizer.createRootTask(Display.DEFAULT_DISPLAY,
- WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
+ WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
} catch (Exception e) {
// teardown to prevent callbacks
mTaskOrganizer.removeListener(this);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
index 6ce4d37..f01fc51 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
@@ -19,6 +19,9 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_MULTI_WINDOW;
+import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_PIP;
+
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
@@ -102,10 +105,10 @@
}
@Test
- public void testOneListenerPerMode() {
- mOrganizer.addListener(new TrackingTaskListener(), WINDOWING_MODE_MULTI_WINDOW);
+ public void testOneListenerPerType() {
+ mOrganizer.addListener(new TrackingTaskListener(), TASK_LISTENER_TYPE_MULTI_WINDOW);
try {
- mOrganizer.addListener(new TrackingTaskListener(), WINDOWING_MODE_MULTI_WINDOW);
+ mOrganizer.addListener(new TrackingTaskListener(), TASK_LISTENER_TYPE_MULTI_WINDOW);
fail("Expected exception due to already registered listener");
} catch (Exception e) {
// Expected failure
@@ -116,7 +119,7 @@
public void testAppearedVanished() {
RunningTaskInfo taskInfo = createTaskInfo(WINDOWING_MODE_MULTI_WINDOW);
TrackingTaskListener listener = new TrackingTaskListener();
- mOrganizer.addListener(listener, WINDOWING_MODE_MULTI_WINDOW);
+ mOrganizer.addListener(listener, TASK_LISTENER_TYPE_MULTI_WINDOW);
mOrganizer.onTaskAppeared(taskInfo, null);
assertTrue(listener.appeared.contains(taskInfo));
@@ -130,7 +133,7 @@
mOrganizer.onTaskAppeared(taskInfo, null);
TrackingTaskListener listener = new TrackingTaskListener();
- mOrganizer.addListener(listener, WINDOWING_MODE_MULTI_WINDOW);
+ mOrganizer.addListener(listener, TASK_LISTENER_TYPE_MULTI_WINDOW);
assertTrue(listener.appeared.contains(taskInfo));
}
@@ -139,8 +142,8 @@
RunningTaskInfo taskInfo = createTaskInfo(WINDOWING_MODE_MULTI_WINDOW);
TrackingTaskListener mwListener = new TrackingTaskListener();
TrackingTaskListener pipListener = new TrackingTaskListener();
- mOrganizer.addListener(mwListener, WINDOWING_MODE_MULTI_WINDOW);
- mOrganizer.addListener(pipListener, WINDOWING_MODE_PINNED);
+ mOrganizer.addListener(mwListener, TASK_LISTENER_TYPE_MULTI_WINDOW);
+ mOrganizer.addListener(pipListener, TASK_LISTENER_TYPE_PIP);
mOrganizer.onTaskAppeared(taskInfo, null);
assertTrue(mwListener.appeared.contains(taskInfo));
assertTrue(pipListener.appeared.isEmpty());
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java
index 7d51886..255e749 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.pip;
+package com.android.wm.shell.pip;
import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_LEAVE_PIP;
import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_TO_PIP;
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsHandlerTest.java
index f514b0b..d9e3148 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsHandlerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsHandlerTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.pip;
+package com.android.wm.shell.pip;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java
index d305c64..92f03e1 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.pip.phone;
+package com.android.wm.shell.pip.phone;
import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTaskOrganizerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTaskOrganizerTest.java
index 663169f..c66ba13 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTaskOrganizerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTaskOrganizerTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.pip.phone;
+package com.android.wm.shell.pip.phone;
import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTouchHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTouchHandlerTest.java
index c96cb20..93a45c4 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTouchHandlerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTouchHandlerTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.pip.phone;
+package com.android.wm.shell.pip.phone;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTouchStateTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTouchStateTest.java
index 2702130..40667f7 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTouchStateTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTouchStateTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.pip.phone;
+package com.android.wm.shell.pip.phone;
import static android.view.MotionEvent.ACTION_BUTTON_PRESS;
import static android.view.MotionEvent.ACTION_DOWN;
diff --git a/libs/hwui/jni/Shader.cpp b/libs/hwui/jni/Shader.cpp
index e76aace..e36e355 100644
--- a/libs/hwui/jni/Shader.cpp
+++ b/libs/hwui/jni/Shader.cpp
@@ -211,14 +211,26 @@
///////////////////////////////////////////////////////////////////////////////////////////////
static jlong RuntimeShader_create(JNIEnv* env, jobject, jlong shaderFactory, jlong matrixPtr,
- jbyteArray inputs, jlong colorSpaceHandle, jboolean isOpaque) {
+ jbyteArray inputs, jlongArray inputShaders, jlong colorSpaceHandle, jboolean isOpaque) {
SkRuntimeEffect* effect = reinterpret_cast<SkRuntimeEffect*>(shaderFactory);
AutoJavaByteArray arInputs(env, inputs);
+ std::vector<sk_sp<SkShader>> shaderVector;
+ if (inputShaders) {
+ jsize shaderCount = env->GetArrayLength(inputShaders);
+ shaderVector.resize(shaderCount);
+ jlong* arrayPtr = env->GetLongArrayElements(inputShaders, NULL);
+ for (int i = 0; i < shaderCount; i++) {
+ shaderVector[i] = sk_ref_sp(reinterpret_cast<SkShader*>(arrayPtr[i]));
+ }
+ env->ReleaseLongArrayElements(inputShaders, arrayPtr, 0);
+ }
+
sk_sp<SkData> fData;
fData = SkData::MakeWithCopy(arInputs.ptr(), arInputs.length());
const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr);
- sk_sp<SkShader> shader = effect->makeShader(fData, nullptr, 0, matrix, isOpaque == JNI_TRUE);
+ sk_sp<SkShader> shader = effect->makeShader(fData, shaderVector.data(), shaderVector.size(),
+ matrix, isOpaque == JNI_TRUE);
ThrowIAE_IfNull(env, shader);
return reinterpret_cast<jlong>(shader.release());
@@ -280,7 +292,7 @@
static const JNINativeMethod gRuntimeShaderMethods[] = {
{ "nativeGetFinalizer", "()J", (void*)RuntimeShader_getNativeFinalizer },
- { "nativeCreate", "(JJ[BJZ)J", (void*)RuntimeShader_create },
+ { "nativeCreate", "(JJ[B[JJZ)J", (void*)RuntimeShader_create },
{ "nativeCreateShaderFactory", "(Ljava/lang/String;)J",
(void*)RuntimeShader_createShaderFactory },
};
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index 5ae9dd2..42cf53b 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -106,11 +106,12 @@
boolean isProviderEnabledForUser(String provider, int userId);
boolean isLocationEnabledForUser(int userId);
void setLocationEnabledForUser(boolean enabled, int userId);
+
void addTestProvider(String name, in ProviderProperties properties, String packageName, String attributionTag);
void removeTestProvider(String provider, String packageName, String attributionTag);
void setTestProviderLocation(String provider, in Location location, String packageName, String attributionTag);
void setTestProviderEnabled(String provider, boolean enabled, String packageName, String attributionTag);
- List<LocationRequest> getTestProviderCurrentRequests(String provider);
+
LocationTime getGnssTimeMillis();
void sendExtraCommand(String provider, String command, inout Bundle extras);
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index f87988c..30a4ada 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -1815,22 +1815,6 @@
public void clearTestProviderStatus(@NonNull String provider) {}
/**
- * Get the last list of {@link LocationRequest}s sent to the provider.
- *
- * @hide
- */
- @TestApi
- @NonNull
- public List<LocationRequest> getTestProviderCurrentRequests(String providerName) {
- Preconditions.checkArgument(providerName != null, "invalid null provider");
- try {
- return mService.getTestProviderCurrentRequests(providerName);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
* Sets a proximity alert for the location given by the position (latitude, longitude) and the
* given radius.
*
diff --git a/media/java/android/media/MediaMetadata.java b/media/java/android/media/MediaMetadata.java
index dbf4ad0..78eeca1 100644
--- a/media/java/android/media/MediaMetadata.java
+++ b/media/java/android/media/MediaMetadata.java
@@ -427,7 +427,7 @@
private MediaMetadata(Parcel in) {
mBundle = in.readBundle();
- mBitmapDimensionLimit = Math.max(in.readInt(), 0);
+ mBitmapDimensionLimit = Math.max(in.readInt(), 1);
}
/**
@@ -518,17 +518,18 @@
/**
* Gets the width/height limit (in pixels) for the bitmaps when this metadata was created.
- * This method returns a positive value or zero.
+ * This method always returns a positive value.
* <p>
- * If it returns a positive value, then all the bitmaps in this metadata has width/height
+ * If it returns {@link Integer#MAX_VALUE}, then no scaling down was applied to the bitmaps
+ * when this metadata was created.
+ * <p>
+ * If it returns another positive value, then all the bitmaps in this metadata has width/height
* not greater than this limit. Bitmaps may have been scaled down according to the limit.
* <p>
- * If it returns zero, then no scaling down was applied to the bitmaps when this metadata
- * was created.
*
* @see Builder#setBitmapDimensionLimit(int)
*/
- public @IntRange(from = 0) int getBitmapDimensionLimit() {
+ public @IntRange(from = 1) int getBitmapDimensionLimit() {
return mBitmapDimensionLimit;
}
@@ -738,7 +739,7 @@
*/
public static final class Builder {
private final Bundle mBundle;
- private int mBitmapDimensionLimit;
+ private int mBitmapDimensionLimit = Integer.MAX_VALUE;
/**
* Create an empty Builder. Any field that should be included in the
@@ -925,14 +926,21 @@
* Bitmaps will be replaced with scaled down copies if their width (or height) is
* larger than {@code bitmapDimensionLimit}.
* <p>
- * In order to unset the limit, pass zero as {@code bitmapDimensionLimit}.
+ * In order to unset the limit, pass {@link Integer#MAX_VALUE} as
+ * {@code bitmapDimensionLimit}.
*
* @param bitmapDimensionLimit The maximum width/height (in pixels) for bitmaps
- * contained in the metadata. Pass {@code 0} to unset the limit.
+ * contained in the metadata. Non-positive values are ignored.
+ * Pass {@link Integer#MAX_VALUE} to unset the limit.
*/
@NonNull
- public Builder setBitmapDimensionLimit(int bitmapDimensionLimit) {
- mBitmapDimensionLimit = Math.max(bitmapDimensionLimit, 0);
+ public Builder setBitmapDimensionLimit(@IntRange(from = 1) int bitmapDimensionLimit) {
+ if (bitmapDimensionLimit > 0) {
+ mBitmapDimensionLimit = bitmapDimensionLimit;
+ } else {
+ Log.w(TAG, "setBitmapDimensionLimit(): Ignoring non-positive bitmapDimensionLimit: "
+ + bitmapDimensionLimit);
+ }
return this;
}
@@ -942,7 +950,7 @@
* @return The new MediaMetadata instance
*/
public MediaMetadata build() {
- if (mBitmapDimensionLimit > 0) {
+ if (mBitmapDimensionLimit != Integer.MAX_VALUE) {
for (String key : mBundle.keySet()) {
Object value = mBundle.get(key);
if (value instanceof Bitmap) {
diff --git a/media/java/android/media/MediaMetadataRetriever.java b/media/java/android/media/MediaMetadataRetriever.java
index cf03b06..835a709 100644
--- a/media/java/android/media/MediaMetadataRetriever.java
+++ b/media/java/android/media/MediaMetadataRetriever.java
@@ -16,10 +16,13 @@
package android.media;
+import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
+
import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentResolver;
import android.content.Context;
@@ -1331,7 +1334,6 @@
* @see MediaFormat#COLOR_RANGE_FULL
*/
public static final int METADATA_KEY_COLOR_RANGE = 37;
- // Add more here...
/**
* This key retrieves the sample rate in Hz, if available.
@@ -1344,4 +1346,13 @@
* This is a signed 32-bit integer formatted as a string in base 10.
*/
public static final int METADATA_KEY_BITS_PER_SAMPLE = 39;
+
+ /**
+ * This key retrieves the video codec mimetype if available.
+ * @hide
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ public static final int METADATA_KEY_VIDEO_CODEC_MIME_TYPE = 40;
+
+ // Add more here...
}
diff --git a/media/java/android/media/musicrecognition/IMusicRecognitionManager.aidl b/media/java/android/media/musicrecognition/IMusicRecognitionManager.aidl
new file mode 100644
index 0000000..9e71afa
--- /dev/null
+++ b/media/java/android/media/musicrecognition/IMusicRecognitionManager.aidl
@@ -0,0 +1,14 @@
+package android.media.musicrecognition;
+
+import android.media.musicrecognition.RecognitionRequest;
+import android.os.IBinder;
+
+/**
+ * Used by {@link MusicRecognitionManager} to tell system server to begin open an audio stream to
+ * the designated lookup service.
+ *
+ * @hide
+ */
+interface IMusicRecognitionManager {
+ void beginRecognition(in RecognitionRequest recognitionRequest, in IBinder callback);
+}
\ No newline at end of file
diff --git a/media/java/android/media/musicrecognition/IMusicRecognitionManagerCallback.aidl b/media/java/android/media/musicrecognition/IMusicRecognitionManagerCallback.aidl
new file mode 100644
index 0000000..e70504f
--- /dev/null
+++ b/media/java/android/media/musicrecognition/IMusicRecognitionManagerCallback.aidl
@@ -0,0 +1,15 @@
+package android.media.musicrecognition;
+
+import android.os.Bundle;
+import android.media.MediaMetadata;
+
+/**
+ * Callback used by system server to notify invoker of {@link MusicRecognitionManager} of the result
+ *
+ * @hide
+ */
+oneway interface IMusicRecognitionManagerCallback {
+ void onRecognitionSucceeded(in MediaMetadata result, in Bundle extras);
+ void onRecognitionFailed(int failureCode);
+ void onAudioStreamClosed();
+}
\ No newline at end of file
diff --git a/media/java/android/media/musicrecognition/IMusicRecognitionService.aidl b/media/java/android/media/musicrecognition/IMusicRecognitionService.aidl
new file mode 100644
index 0000000..26543ed
--- /dev/null
+++ b/media/java/android/media/musicrecognition/IMusicRecognitionService.aidl
@@ -0,0 +1,18 @@
+package android.media.musicrecognition;
+
+import android.media.AudioFormat;
+import android.os.ParcelFileDescriptor;
+import android.os.IBinder;
+import android.media.musicrecognition.IMusicRecognitionServiceCallback;
+
+/**
+ * Interface from the system to a {@link MusicRecognitionService}.
+ *
+ * @hide
+ */
+oneway interface IMusicRecognitionService {
+ void onAudioStreamStarted(
+ in ParcelFileDescriptor fd,
+ in AudioFormat audioFormat,
+ in IMusicRecognitionServiceCallback callback);
+}
\ No newline at end of file
diff --git a/media/java/android/media/musicrecognition/IMusicRecognitionServiceCallback.aidl b/media/java/android/media/musicrecognition/IMusicRecognitionServiceCallback.aidl
new file mode 100644
index 0000000..15215c4
--- /dev/null
+++ b/media/java/android/media/musicrecognition/IMusicRecognitionServiceCallback.aidl
@@ -0,0 +1,15 @@
+package android.media.musicrecognition;
+
+import android.os.Bundle;
+import android.media.MediaMetadata;
+
+/**
+ * Interface from a {@MusicRecognitionService} the system.
+ *
+ * @hide
+ */
+oneway interface IMusicRecognitionServiceCallback {
+ void onRecognitionSucceeded(in MediaMetadata result, in Bundle extras);
+
+ void onRecognitionFailed(int failureCode);
+}
\ No newline at end of file
diff --git a/media/java/android/media/musicrecognition/MusicRecognitionManager.java b/media/java/android/media/musicrecognition/MusicRecognitionManager.java
new file mode 100644
index 0000000..c7f55df
--- /dev/null
+++ b/media/java/android/media/musicrecognition/MusicRecognitionManager.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.musicrecognition;
+
+import static java.util.Objects.requireNonNull;
+
+import android.annotation.CallbackExecutor;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
+import android.annotation.SystemService;
+import android.annotation.TestApi;
+import android.content.Context;
+import android.media.MediaMetadata;
+import android.os.Bundle;
+import android.os.RemoteException;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.concurrent.Executor;
+
+/**
+ * System service that manages music recognition.
+ *
+ * @hide
+ */
+@SystemApi
+@TestApi
+@SystemService(Context.MUSIC_RECOGNITION_SERVICE)
+public class MusicRecognitionManager {
+
+ /**
+ * Error code provided by RecognitionCallback#onRecognitionFailed()
+ *
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = {"RECOGNITION_FAILED_"},
+ value = {RECOGNITION_FAILED_UNKNOWN,
+ RECOGNITION_FAILED_NOT_FOUND,
+ RECOGNITION_FAILED_NO_CONNECTIVITY,
+ RECOGNITION_FAILED_SERVICE_UNAVAILABLE,
+ RECOGNITION_FAILED_SERVICE_KILLED,
+ RECOGNITION_FAILED_TIMEOUT,
+ RECOGNITION_FAILED_AUDIO_UNAVAILABLE})
+ public @interface RecognitionFailureCode {
+ }
+
+ /** Catchall error code. */
+ public static final int RECOGNITION_FAILED_UNKNOWN = -1;
+ /** Recognition was performed but no result could be identified. */
+ public static final int RECOGNITION_FAILED_NOT_FOUND = 1;
+ /** Recognition failed because the server couldn't be reached. */
+ public static final int RECOGNITION_FAILED_NO_CONNECTIVITY = 2;
+ /**
+ * Recognition was not possible because the application which provides it is not available (for
+ * example, disabled).
+ */
+ public static final int RECOGNITION_FAILED_SERVICE_UNAVAILABLE = 3;
+ /** Recognition failed because the recognizer was killed. */
+ public static final int RECOGNITION_FAILED_SERVICE_KILLED = 5;
+ /** Recognition attempt timed out. */
+ public static final int RECOGNITION_FAILED_TIMEOUT = 6;
+ /** Recognition failed due to an issue with obtaining an audio stream. */
+ public static final int RECOGNITION_FAILED_AUDIO_UNAVAILABLE = 7;
+
+ /** Callback interface for the caller of this api. */
+ public interface RecognitionCallback {
+ /**
+ * Should be invoked by receiving app with the result of the search.
+ *
+ * @param recognitionRequest original request that started the recognition
+ * @param result result of the search
+ * @param extras extra data to be supplied back to the caller. Note that all
+ * executable parameters and file descriptors would be removed from the
+ * supplied bundle
+ */
+ void onRecognitionSucceeded(@NonNull RecognitionRequest recognitionRequest,
+ @NonNull MediaMetadata result, @Nullable Bundle extras);
+
+ /**
+ * Invoked when the search is not successful (possibly but not necessarily due to error).
+ *
+ * @param recognitionRequest original request that started the recognition
+ * @param failureCode failure code describing reason for failure
+ */
+ void onRecognitionFailed(@NonNull RecognitionRequest recognitionRequest,
+ @RecognitionFailureCode int failureCode);
+
+ /**
+ * Invoked by the system once the audio stream is closed either due to error, reaching the
+ * limit, or the remote service closing the stream. Always called per
+ * #beingStreamingSearch() invocation.
+ */
+ void onAudioStreamClosed();
+ }
+
+ private final IMusicRecognitionManager mService;
+
+ /** @hide */
+ public MusicRecognitionManager(IMusicRecognitionManager service) {
+ mService = service;
+ }
+
+ /**
+ * Constructs an {@link android.media.AudioRecord} from the given parameters and streams the
+ * audio bytes to the designated cloud lookup service. After the lookup is done, the given
+ * callback will be invoked by the system with the result or lack thereof.
+ *
+ * @param recognitionRequest audio parameters for the stream to search
+ * @param callbackExecutor where the callback is invoked
+ * @param callback invoked when the result is available
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.MANAGE_MUSIC_RECOGNITION)
+ public void beginStreamingSearch(
+ @NonNull RecognitionRequest recognitionRequest,
+ @NonNull @CallbackExecutor Executor callbackExecutor,
+ @NonNull RecognitionCallback callback) {
+ try {
+ mService.beginRecognition(
+ requireNonNull(recognitionRequest),
+ new MusicRecognitionCallbackWrapper(
+ requireNonNull(recognitionRequest),
+ requireNonNull(callback),
+ requireNonNull(callbackExecutor)));
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ private final class MusicRecognitionCallbackWrapper extends
+ IMusicRecognitionManagerCallback.Stub {
+
+ @NonNull
+ private final RecognitionRequest mRecognitionRequest;
+ @NonNull
+ private final RecognitionCallback mCallback;
+ @NonNull
+ private final Executor mCallbackExecutor;
+
+ MusicRecognitionCallbackWrapper(
+ RecognitionRequest recognitionRequest,
+ RecognitionCallback callback,
+ Executor callbackExecutor) {
+ mRecognitionRequest = recognitionRequest;
+ mCallback = callback;
+ mCallbackExecutor = callbackExecutor;
+ }
+
+ @Override
+ public void onRecognitionSucceeded(MediaMetadata result, Bundle extras) {
+ mCallbackExecutor.execute(
+ () -> mCallback.onRecognitionSucceeded(mRecognitionRequest, result, extras));
+ }
+
+ @Override
+ public void onRecognitionFailed(@RecognitionFailureCode int failureCode) {
+ mCallbackExecutor.execute(
+ () -> mCallback.onRecognitionFailed(mRecognitionRequest, failureCode));
+ }
+
+ @Override
+ public void onAudioStreamClosed() {
+ mCallbackExecutor.execute(mCallback::onAudioStreamClosed);
+ }
+ }
+}
diff --git a/media/java/android/media/musicrecognition/MusicRecognitionService.java b/media/java/android/media/musicrecognition/MusicRecognitionService.java
new file mode 100644
index 0000000..b75d2c4
--- /dev/null
+++ b/media/java/android/media/musicrecognition/MusicRecognitionService.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.musicrecognition;
+
+import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
+import android.app.Service;
+import android.content.Intent;
+import android.media.AudioFormat;
+import android.media.MediaMetadata;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
+import android.util.Log;
+
+/**
+ * Implemented by an app that wants to offer music search lookups. The system will start the
+ * service and stream up to 16 seconds of audio over the given file descriptor.
+ *
+ * @hide
+ */
+@SystemApi
+@TestApi
+public abstract class MusicRecognitionService extends Service {
+
+ private static final String TAG = MusicRecognitionService.class.getSimpleName();
+
+ /** Callback for the result of the remote search. */
+ public interface Callback {
+ /**
+ * Call this method to pass back a successful search result.
+ *
+ * @param result successful result of the search
+ * @param extras extra data to be supplied back to the caller. Note that all executable
+ * parameters and file descriptors would be removed from the supplied bundle
+ */
+ void onRecognitionSucceeded(@NonNull MediaMetadata result, @Nullable Bundle extras);
+
+ /**
+ * Call this method if the search does not find a result on an error occurred.
+ */
+ void onRecognitionFailed(@MusicRecognitionManager.RecognitionFailureCode int failureCode);
+ }
+
+ /**
+ * Action used to start this service.
+ *
+ * @hide
+ */
+ public static final String ACTION_MUSIC_SEARCH_LOOKUP =
+ "android.service.musicrecognition.MUSIC_RECOGNITION";
+
+ private Handler mHandler;
+ private final IMusicRecognitionService mServiceInterface =
+ new IMusicRecognitionService.Stub() {
+ @Override
+ public void onAudioStreamStarted(ParcelFileDescriptor fd,
+ AudioFormat audioFormat,
+ IMusicRecognitionServiceCallback callback) {
+ mHandler.sendMessage(
+ obtainMessage(MusicRecognitionService.this::onRecognize, fd,
+ audioFormat,
+ new Callback() {
+ @Override
+ public void onRecognitionSucceeded(
+ @NonNull MediaMetadata result,
+ @Nullable Bundle extras) {
+ try {
+ callback.onRecognitionSucceeded(result, extras);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ }
+
+ @Override
+ public void onRecognitionFailed(int failureCode) {
+ try {
+ callback.onRecognitionFailed(failureCode);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ }
+ }));
+ }
+ };
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ mHandler = new Handler(Looper.getMainLooper(), null, true);
+ }
+
+ /**
+ * Read audio from this stream. You must invoke the callback whether the music is recognized or
+ * not.
+ *
+ * @param stream containing music to be recognized. Close when you are finished.
+ * @param audioFormat describes sample rate, channels and endianness of the stream
+ * @param callback to invoke after lookup is finished. Must always be called.
+ */
+ public abstract void onRecognize(@NonNull ParcelFileDescriptor stream,
+ @NonNull AudioFormat audioFormat,
+ @NonNull Callback callback);
+
+ /**
+ * @hide
+ */
+ @Nullable
+ @Override
+ public IBinder onBind(@NonNull Intent intent) {
+ if (ACTION_MUSIC_SEARCH_LOOKUP.equals(intent.getAction())) {
+ return mServiceInterface.asBinder();
+ }
+ Log.w(TAG,
+ "Tried to bind to wrong intent (should be " + ACTION_MUSIC_SEARCH_LOOKUP + ": "
+ + intent);
+ return null;
+ }
+}
diff --git a/media/java/android/media/musicrecognition/RecognitionRequest.aidl b/media/java/android/media/musicrecognition/RecognitionRequest.aidl
new file mode 100644
index 0000000..757b5701
--- /dev/null
+++ b/media/java/android/media/musicrecognition/RecognitionRequest.aidl
@@ -0,0 +1,18 @@
+/* Copyright 2020, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.media.musicrecognition;
+
+parcelable RecognitionRequest;
\ No newline at end of file
diff --git a/media/java/android/media/musicrecognition/RecognitionRequest.java b/media/java/android/media/musicrecognition/RecognitionRequest.java
new file mode 100644
index 0000000..65b2ccd
--- /dev/null
+++ b/media/java/android/media/musicrecognition/RecognitionRequest.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.musicrecognition;
+
+import static android.media.AudioAttributes.CONTENT_TYPE_MUSIC;
+import static android.media.AudioFormat.ENCODING_PCM_16BIT;
+
+import static java.util.Objects.requireNonNull;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
+import android.media.AudioAttributes;
+import android.media.AudioFormat;
+import android.media.AudioRecord;
+import android.media.MediaRecorder;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Encapsulates parameters for making music recognition queries via {@link MusicRecognitionManager}.
+ *
+ * @hide
+ */
+@SystemApi
+@TestApi
+public final class RecognitionRequest implements Parcelable {
+ @NonNull private final AudioAttributes mAudioAttributes;
+ @NonNull private final AudioFormat mAudioFormat;
+ private final int mCaptureSession;
+ private final int mMaxAudioLengthSeconds;
+ private final int mIgnoreBeginningFrames;
+
+ private RecognitionRequest(Builder b) {
+ mAudioAttributes = requireNonNull(b.mAudioAttributes);
+ mAudioFormat = requireNonNull(b.mAudioFormat);
+ mCaptureSession = b.mCaptureSession;
+ mMaxAudioLengthSeconds = b.mMaxAudioLengthSeconds;
+ mIgnoreBeginningFrames = b.mIgnoreBeginningFrames;
+ }
+
+ @NonNull
+ public AudioAttributes getAudioAttributes() {
+ return mAudioAttributes;
+ }
+
+ @NonNull
+ public AudioFormat getAudioFormat() {
+ return mAudioFormat;
+ }
+
+ public int getCaptureSession() {
+ return mCaptureSession;
+ }
+
+ @SuppressWarnings("MethodNameUnits")
+ public int getMaxAudioLengthSeconds() {
+ return mMaxAudioLengthSeconds;
+ }
+
+ public int getIgnoreBeginningFrames() {
+ return mIgnoreBeginningFrames;
+ }
+
+ /**
+ * Builder for constructing StreamSearchRequest objects.
+ *
+ * @hide
+ */
+ @SystemApi
+ @TestApi
+ public static final class Builder {
+ private AudioFormat mAudioFormat = new AudioFormat.Builder()
+ .setSampleRate(16000)
+ .setEncoding(ENCODING_PCM_16BIT)
+ .build();
+ private AudioAttributes mAudioAttributes = new AudioAttributes.Builder()
+ .setContentType(CONTENT_TYPE_MUSIC)
+ .build();
+ private int mCaptureSession = MediaRecorder.AudioSource.MIC;
+ private int mMaxAudioLengthSeconds = 24; // Max enforced in system server.
+ private int mIgnoreBeginningFrames = 0;
+
+ /** Attributes passed to the constructed {@link AudioRecord}. */
+ @NonNull
+ public Builder setAudioAttributes(@NonNull AudioAttributes audioAttributes) {
+ mAudioAttributes = audioAttributes;
+ return this;
+ }
+
+ /** AudioFormat passed to the constructed {@link AudioRecord}. */
+ @NonNull
+ public Builder setAudioFormat(@NonNull AudioFormat audioFormat) {
+ mAudioFormat = audioFormat;
+ return this;
+ }
+
+ /** Constant from {@link android.media.MediaRecorder.AudioSource}. */
+ @NonNull
+ public Builder setCaptureSession(int captureSession) {
+ mCaptureSession = captureSession;
+ return this;
+ }
+
+ /** Maximum number of seconds to stream from the audio source. */
+ @NonNull
+ public Builder setMaxAudioLengthSeconds(int maxAudioLengthSeconds) {
+ mMaxAudioLengthSeconds = maxAudioLengthSeconds;
+ return this;
+ }
+
+ /** Number of samples to drop from the start of the stream. */
+ @NonNull
+ public Builder setIgnoreBeginningFrames(int ignoreBeginningFrames) {
+ mIgnoreBeginningFrames = ignoreBeginningFrames;
+ return this;
+ }
+
+ /** Returns the constructed request. */
+ @NonNull
+ public RecognitionRequest build() {
+ return new RecognitionRequest(this);
+ }
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeParcelable(mAudioFormat, flags);
+ dest.writeParcelable(mAudioAttributes, flags);
+ dest.writeInt(mCaptureSession);
+ dest.writeInt(mMaxAudioLengthSeconds);
+ dest.writeInt(mIgnoreBeginningFrames);
+ }
+
+ private RecognitionRequest(Parcel in) {
+ mAudioFormat = in.readParcelable(AudioFormat.class.getClassLoader());
+ mAudioAttributes = in.readParcelable(AudioAttributes.class.getClassLoader());
+ mCaptureSession = in.readInt();
+ mMaxAudioLengthSeconds = in.readInt();
+ mIgnoreBeginningFrames = in.readInt();
+ }
+
+ @NonNull public static final Creator<RecognitionRequest> CREATOR =
+ new Creator<RecognitionRequest>() {
+
+ @Override
+ public RecognitionRequest createFromParcel(Parcel p) {
+ return new RecognitionRequest(p);
+ }
+
+ @Override
+ public RecognitionRequest[] newArray(int size) {
+ return new RecognitionRequest[size];
+ }
+ };
+}
diff --git a/media/java/android/media/tv/ITvInputManager.aidl b/media/java/android/media/tv/ITvInputManager.aidl
index 4380c13..ed99fad 100644
--- a/media/java/android/media/tv/ITvInputManager.aidl
+++ b/media/java/android/media/tv/ITvInputManager.aidl
@@ -25,7 +25,7 @@
import android.media.tv.ITvInputHardware;
import android.media.tv.ITvInputHardwareCallback;
import android.media.tv.ITvInputManagerCallback;
-import android.media.tv.TvChannelInfo;
+import android.media.tv.TunedInfo;
import android.media.tv.TvContentRatingSystemInfo;
import android.media.tv.TvInputHardwareInfo;
import android.media.tv.TvInputInfo;
@@ -89,7 +89,7 @@
void timeShiftSetPlaybackParams(in IBinder sessionToken, in PlaybackParams params, int userId);
void timeShiftEnablePositionTracking(in IBinder sessionToken, boolean enable, int userId);
- List<TvChannelInfo> getCurrentTvChannelInfos(int userId);
+ List<TunedInfo> getCurrentTunedInfos(int userId);
// For the recording session
void startRecording(in IBinder sessionToken, in Uri programUri, in Bundle params, int userId);
diff --git a/media/java/android/media/tv/ITvInputManagerCallback.aidl b/media/java/android/media/tv/ITvInputManagerCallback.aidl
index 9f80bf5..3128ba7 100644
--- a/media/java/android/media/tv/ITvInputManagerCallback.aidl
+++ b/media/java/android/media/tv/ITvInputManagerCallback.aidl
@@ -16,7 +16,7 @@
package android.media.tv;
-import android.media.tv.TvChannelInfo;
+import android.media.tv.TunedInfo;
import android.media.tv.TvInputInfo;
/**
@@ -29,5 +29,5 @@
void onInputUpdated(in String inputId);
void onInputStateChanged(in String inputId, int state);
void onTvInputInfoUpdated(in TvInputInfo TvInputInfo);
- void onCurrentTvChannelInfosUpdated(in List<TvChannelInfo> currentTvChannelInfos);
+ void onCurrentTunedInfosUpdated(in List<TunedInfo> currentTunedInfos);
}
diff --git a/media/java/android/media/tv/TvChannelInfo.aidl b/media/java/android/media/tv/TunedInfo.aidl
similarity index 95%
rename from media/java/android/media/tv/TvChannelInfo.aidl
rename to media/java/android/media/tv/TunedInfo.aidl
index 71cd0a7..b7c1d52 100644
--- a/media/java/android/media/tv/TvChannelInfo.aidl
+++ b/media/java/android/media/tv/TunedInfo.aidl
@@ -16,4 +16,4 @@
package android.media.tv;
-parcelable TvChannelInfo;
+parcelable TunedInfo;
diff --git a/media/java/android/media/tv/TvChannelInfo.java b/media/java/android/media/tv/TunedInfo.java
similarity index 88%
rename from media/java/android/media/tv/TvChannelInfo.java
rename to media/java/android/media/tv/TunedInfo.java
index 11cb1f7..6fc5784 100644
--- a/media/java/android/media/tv/TvChannelInfo.java
+++ b/media/java/android/media/tv/TunedInfo.java
@@ -31,11 +31,12 @@
/**
- * This class is used to specify information of a TV channel.
+ * Contains information about a {@link TvInputService.Session} that is currently tuned to a channel
+ * or pass-through input.
* @hide
*/
-public final class TvChannelInfo implements Parcelable {
- static final String TAG = "TvChannelInfo";
+public final class TunedInfo implements Parcelable {
+ static final String TAG = "TunedInfo";
/**
* App tag for {@link #getAppTag()}: the corresponding application of the channel is the same as
@@ -67,21 +68,21 @@
@Retention(RetentionPolicy.SOURCE)
public @interface AppType {}
- public static final @NonNull Parcelable.Creator<TvChannelInfo> CREATOR =
- new Parcelable.Creator<TvChannelInfo>() {
+ public static final @NonNull Parcelable.Creator<TunedInfo> CREATOR =
+ new Parcelable.Creator<TunedInfo>() {
@Override
- public TvChannelInfo createFromParcel(Parcel source) {
+ public TunedInfo createFromParcel(Parcel source) {
try {
- return new TvChannelInfo(source);
+ return new TunedInfo(source);
} catch (Exception e) {
- Log.e(TAG, "Exception creating TvChannelInfo from parcel", e);
+ Log.e(TAG, "Exception creating TunedInfo from parcel", e);
return null;
}
}
@Override
- public TvChannelInfo[] newArray(int size) {
- return new TvChannelInfo[size];
+ public TunedInfo[] newArray(int size) {
+ return new TunedInfo[size];
}
};
@@ -94,7 +95,7 @@
private final int mAppTag;
/** @hide */
- public TvChannelInfo(
+ public TunedInfo(
String inputId, @Nullable Uri channelUri, boolean isRecordingSession,
boolean isForeground, @AppType int appType, int appTag) {
mInputId = inputId;
@@ -106,7 +107,7 @@
}
- private TvChannelInfo(Parcel source) {
+ private TunedInfo(Parcel source) {
mInputId = source.readString();
String uriString = source.readString();
mChannelUri = uriString == null ? null : Uri.parse(uriString);
@@ -194,11 +195,11 @@
@Override
public boolean equals(Object o) {
- if (!(o instanceof TvChannelInfo)) {
+ if (!(o instanceof TunedInfo)) {
return false;
}
- TvChannelInfo other = (TvChannelInfo) o;
+ TunedInfo other = (TunedInfo) o;
return TextUtils.equals(mInputId, other.getInputId())
&& Objects.equals(mChannelUri, other.mChannelUri)
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index c80f3c6..73539fb 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -901,12 +901,13 @@
}
/**
- * This is called when the information about current TV channels has been updated.
+ * This is called when the information about current tuned information has been updated.
*
- * @param tvChannelInfos a list of {@link TvChannelInfo} objects of new current channels.
+ * @param tunedInfos a list of {@link TunedInfo} objects of new tuned information.
* @hide
*/
- public void onCurrentTvChannelInfosUpdated(@NonNull List<TvChannelInfo> tvChannelInfos) {
+ public void onCurrentTunedInfosUpdated(
+ @NonNull List<TunedInfo> tunedInfos) {
}
}
@@ -968,12 +969,11 @@
});
}
- public void postCurrentTvChannelInfosUpdated(
- final List<TvChannelInfo> currentTvChannelInfos) {
+ public void onCurrentTunedInfosUpdated(final List<TunedInfo> currentTunedInfos) {
mHandler.post(new Runnable() {
@Override
public void run() {
- mCallback.onCurrentTvChannelInfosUpdated(currentTvChannelInfos);
+ mCallback.onCurrentTunedInfosUpdated(currentTunedInfos);
}
});
}
@@ -1283,10 +1283,10 @@
}
@Override
- public void onCurrentTvChannelInfosUpdated(List<TvChannelInfo> currentTvChannelInfos) {
+ public void onCurrentTunedInfosUpdated(List<TunedInfo> currentTunedInfos) {
synchronized (mLock) {
for (TvInputCallbackRecord record : mCallbackRecords) {
- record.postCurrentTvChannelInfosUpdated(currentTvChannelInfos);
+ record.onCurrentTunedInfosUpdated(currentTunedInfos);
}
}
}
@@ -1981,18 +1981,18 @@
}
/**
- * Returns the list of TV channel information for {@link TvInputService.Session} that are
+ * Returns the list of session information for {@link TvInputService.Session} that are
* currently in use.
* <p> Permission com.android.providers.tv.permission.ACCESS_WATCHED_PROGRAMS is required to get
- * the channel URIs. If the permission is not granted, {@link TvChannelInfo#getChannelUri()}
- * returns {@code null}.
+ * the channel URIs. If the permission is not granted,
+ * {@link TunedInfo#getChannelUri()} returns {@code null}.
* @hide
*/
@RequiresPermission("com.android.providers.tv.permission.ACCESS_WATCHED_PROGRAMS")
@NonNull
- public List<TvChannelInfo> getCurrentTvChannelInfos() {
+ public List<TunedInfo> getCurrentTunedInfos() {
try {
- return mService.getCurrentTvChannelInfos(mUserId);
+ return mService.getCurrentTunedInfos(mUserId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/non-updatable-api/current.txt b/non-updatable-api/current.txt
index a0aa0e0..36207c9 100644
--- a/non-updatable-api/current.txt
+++ b/non-updatable-api/current.txt
@@ -26366,7 +26366,7 @@
method public boolean containsKey(String);
method public int describeContents();
method public android.graphics.Bitmap getBitmap(String);
- method @IntRange(from=0) public int getBitmapDimensionLimit();
+ method @IntRange(from=1) public int getBitmapDimensionLimit();
method @NonNull public android.media.MediaDescription getDescription();
method public long getLong(String);
method public android.media.Rating getRating(String);
@@ -26416,7 +26416,7 @@
method public android.media.MediaMetadata.Builder putRating(String, android.media.Rating);
method public android.media.MediaMetadata.Builder putString(String, String);
method public android.media.MediaMetadata.Builder putText(String, CharSequence);
- method @NonNull public android.media.MediaMetadata.Builder setBitmapDimensionLimit(int);
+ method @NonNull public android.media.MediaMetadata.Builder setBitmapDimensionLimit(@IntRange(from=1) int);
}
@Deprecated public abstract class MediaMetadataEditor {
diff --git a/non-updatable-api/module-lib-current.txt b/non-updatable-api/module-lib-current.txt
index 6e3cec6..b19ce48 100644
--- a/non-updatable-api/module-lib-current.txt
+++ b/non-updatable-api/module-lib-current.txt
@@ -53,6 +53,10 @@
field public static final int FLAG_FROM_KEY = 4096; // 0x1000
}
+ public class MediaMetadataRetriever implements java.lang.AutoCloseable {
+ field public static final int METADATA_KEY_VIDEO_CODEC_MIME_TYPE = 40; // 0x28
+ }
+
}
package android.media.session {
diff --git a/non-updatable-api/system-current.txt b/non-updatable-api/system-current.txt
index 525670c..515c273 100644
--- a/non-updatable-api/system-current.txt
+++ b/non-updatable-api/system-current.txt
@@ -38,6 +38,7 @@
field public static final String BIND_EXTERNAL_STORAGE_SERVICE = "android.permission.BIND_EXTERNAL_STORAGE_SERVICE";
field public static final String BIND_IMS_SERVICE = "android.permission.BIND_IMS_SERVICE";
field public static final String BIND_KEYGUARD_APPWIDGET = "android.permission.BIND_KEYGUARD_APPWIDGET";
+ field public static final String BIND_MUSIC_RECOGNITION_SERVICE = "android.permission.BIND_MUSIC_RECOGNITION_SERVICE";
field public static final String BIND_NETWORK_RECOMMENDATION_SERVICE = "android.permission.BIND_NETWORK_RECOMMENDATION_SERVICE";
field public static final String BIND_NOTIFICATION_ASSISTANT_SERVICE = "android.permission.BIND_NOTIFICATION_ASSISTANT_SERVICE";
field public static final String BIND_PHONE_ACCOUNT_SUGGESTION_SERVICE = "android.permission.BIND_PHONE_ACCOUNT_SUGGESTION_SERVICE";
@@ -120,6 +121,7 @@
field public static final String MANAGE_DEBUGGING = "android.permission.MANAGE_DEBUGGING";
field public static final String MANAGE_FACTORY_RESET_PROTECTION = "android.permission.MANAGE_FACTORY_RESET_PROTECTION";
field public static final String MANAGE_IPSEC_TUNNELS = "android.permission.MANAGE_IPSEC_TUNNELS";
+ field public static final String MANAGE_MUSIC_RECOGNITION = "android.permission.MANAGE_MUSIC_RECOGNITION";
field public static final String MANAGE_ONE_TIME_PERMISSION_SESSIONS = "android.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS";
field public static final String MANAGE_ROLE_HOLDERS = "android.permission.MANAGE_ROLE_HOLDERS";
field public static final String MANAGE_ROLLBACKS = "android.permission.MANAGE_ROLLBACKS";
@@ -4557,6 +4559,58 @@
}
+package android.media.musicrecognition {
+
+ public class MusicRecognitionManager {
+ method @RequiresPermission(android.Manifest.permission.MANAGE_MUSIC_RECOGNITION) public void beginStreamingSearch(@NonNull android.media.musicrecognition.RecognitionRequest, @NonNull java.util.concurrent.Executor, @NonNull android.media.musicrecognition.MusicRecognitionManager.RecognitionCallback);
+ field public static final int RECOGNITION_FAILED_AUDIO_UNAVAILABLE = 7; // 0x7
+ field public static final int RECOGNITION_FAILED_NOT_FOUND = 1; // 0x1
+ field public static final int RECOGNITION_FAILED_NO_CONNECTIVITY = 2; // 0x2
+ field public static final int RECOGNITION_FAILED_SERVICE_KILLED = 5; // 0x5
+ field public static final int RECOGNITION_FAILED_SERVICE_UNAVAILABLE = 3; // 0x3
+ field public static final int RECOGNITION_FAILED_TIMEOUT = 6; // 0x6
+ field public static final int RECOGNITION_FAILED_UNKNOWN = -1; // 0xffffffff
+ }
+
+ public static interface MusicRecognitionManager.RecognitionCallback {
+ method public void onAudioStreamClosed();
+ method public void onRecognitionFailed(@NonNull android.media.musicrecognition.RecognitionRequest, int);
+ method public void onRecognitionSucceeded(@NonNull android.media.musicrecognition.RecognitionRequest, @NonNull android.media.MediaMetadata, @Nullable android.os.Bundle);
+ }
+
+ public abstract class MusicRecognitionService extends android.app.Service {
+ ctor public MusicRecognitionService();
+ method public abstract void onRecognize(@NonNull android.os.ParcelFileDescriptor, @NonNull android.media.AudioFormat, @NonNull android.media.musicrecognition.MusicRecognitionService.Callback);
+ }
+
+ public static interface MusicRecognitionService.Callback {
+ method public void onRecognitionFailed(int);
+ method public void onRecognitionSucceeded(@NonNull android.media.MediaMetadata, @Nullable android.os.Bundle);
+ }
+
+ public final class RecognitionRequest implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public android.media.AudioAttributes getAudioAttributes();
+ method @NonNull public android.media.AudioFormat getAudioFormat();
+ method public int getCaptureSession();
+ method public int getIgnoreBeginningFrames();
+ method public int getMaxAudioLengthSeconds();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.media.musicrecognition.RecognitionRequest> CREATOR;
+ }
+
+ public static final class RecognitionRequest.Builder {
+ ctor public RecognitionRequest.Builder();
+ method @NonNull public android.media.musicrecognition.RecognitionRequest build();
+ method @NonNull public android.media.musicrecognition.RecognitionRequest.Builder setAudioAttributes(@NonNull android.media.AudioAttributes);
+ method @NonNull public android.media.musicrecognition.RecognitionRequest.Builder setAudioFormat(@NonNull android.media.AudioFormat);
+ method @NonNull public android.media.musicrecognition.RecognitionRequest.Builder setCaptureSession(int);
+ method @NonNull public android.media.musicrecognition.RecognitionRequest.Builder setIgnoreBeginningFrames(int);
+ method @NonNull public android.media.musicrecognition.RecognitionRequest.Builder setMaxAudioLengthSeconds(int);
+ }
+
+}
+
package android.media.session {
public final class MediaSessionManager {
@@ -10359,6 +10413,7 @@
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean isIccLockEnabled();
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isIdle();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isLteCdmaEvdoGsmWcdmaEnabled();
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isMobileDataPolicyEnabled(int);
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isOffhook();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isOpportunisticNetworkEnabled();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isPotentialEmergencyNumber(@NonNull String);
@@ -10389,6 +10444,7 @@
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataActivationState(int);
method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataEnabled(int, boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataRoamingEnabled(boolean);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setMobileDataPolicyEnabledStatus(int, boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setMultiSimCarrierRestriction(boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setOpportunisticNetworkState(boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setPreferredNetworkTypeBitmask(long);
@@ -10439,6 +10495,8 @@
field public static final int INVALID_EMERGENCY_NUMBER_DB_VERSION = -1; // 0xffffffff
field public static final int KEY_TYPE_EPDG = 1; // 0x1
field public static final int KEY_TYPE_WLAN = 2; // 0x2
+ field public static final int MOBILE_DATA_POLICY_DATA_ON_NON_DEFAULT_DURING_VOICE_CALL = 1; // 0x1
+ field public static final int MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED = 2; // 0x2
field public static final long NETWORK_TYPE_BITMASK_1xRTT = 64L; // 0x40L
field public static final long NETWORK_TYPE_BITMASK_CDMA = 8L; // 0x8L
field public static final long NETWORK_TYPE_BITMASK_EDGE = 2L; // 0x2L
diff --git a/packages/CarSystemUI/res/layout/sysui_overlay_window.xml b/packages/CarSystemUI/res/layout/sysui_overlay_window.xml
index e7295aa..2c97889 100644
--- a/packages/CarSystemUI/res/layout/sysui_overlay_window.xml
+++ b/packages/CarSystemUI/res/layout/sysui_overlay_window.xml
@@ -25,8 +25,7 @@
<ViewStub android:id="@+id/notification_panel_stub"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:layout="@layout/notification_panel_container"
- android:layout_marginBottom="@dimen/car_bottom_navigation_bar_height"/>
+ android:layout="@layout/notification_panel_container"/>
<ViewStub android:id="@+id/keyguard_stub"
android:layout_width="match_parent"
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewController.java b/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewController.java
index b647f13..4b66069 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewController.java
@@ -32,6 +32,7 @@
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
+import android.view.WindowInsets;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
@@ -82,7 +83,6 @@
private final StatusBarStateController mStatusBarStateController;
private final boolean mEnableHeadsUpNotificationWhenNotificationShadeOpen;
private final NotificationVisibilityLogger mNotificationVisibilityLogger;
- private final int mNavBarHeight;
private float mInitialBackgroundAlpha;
private float mBackgroundAlphaDiff;
@@ -97,6 +97,7 @@
private boolean mNotificationListAtEndAtTimeOfTouch;
private boolean mIsSwipingVerticallyToClose;
private boolean mIsNotificationCardSwiping;
+ private boolean mImeVisible = false;
private OnUnseenCountUpdateListener mUnseenCountUpdateListener;
@@ -139,8 +140,6 @@
mStatusBarStateController = statusBarStateController;
mNotificationVisibilityLogger = notificationVisibilityLogger;
- mNavBarHeight = mResources.getDimensionPixelSize(R.dimen.car_bottom_navigation_bar_height);
-
mCommandQueue.addCallback(this);
// Notification background setup.
@@ -189,19 +188,7 @@
if (mContext.getDisplayId() != displayId) {
return;
}
- boolean isKeyboardVisible = (vis & InputMethodService.IME_VISIBLE) != 0;
- int bottomMargin = isKeyboardVisible ? 0 : mNavBarHeight;
- ViewGroup container = (ViewGroup) getLayout();
- if (container == null) {
- // Notification panel hasn't been inflated before. We shouldn't try to update the layout
- // params.
- return;
- }
-
- ViewGroup.MarginLayoutParams params =
- (ViewGroup.MarginLayoutParams) container.getLayoutParams();
- params.setMargins(params.leftMargin, params.topMargin, params.rightMargin, bottomMargin);
- container.setLayoutParams(params);
+ mImeVisible = (vis & InputMethodService.IME_VISIBLE) != 0;
}
// OverlayViewController
@@ -229,7 +216,7 @@
@Override
protected int getInsetTypesToFit() {
- return 0;
+ return WindowInsets.Type.navigationBars();
}
@Override
@@ -237,6 +224,12 @@
return mEnableHeadsUpNotificationWhenNotificationShadeOpen;
}
+ @Override
+ protected boolean shouldUseStableInsets() {
+ // When IME is visible, then the inset from the nav bar should not be applied.
+ return !mImeVisible;
+ }
+
/** Reinflates the view. */
public void reinflate() {
ViewGroup container = (ViewGroup) getLayout();
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserGridRecyclerView.java b/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserGridRecyclerView.java
index 023b5b4..6d63e31 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserGridRecyclerView.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserGridRecyclerView.java
@@ -567,6 +567,9 @@
Log.e(TAG, "Failed to switch to new user: " + user.id);
}
}
+ if (mAddUserView != null) {
+ mAddUserView.setEnabled(true);
+ }
}
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewController.java b/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewController.java
index 8adc1ad..6c3a632 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewController.java
@@ -168,6 +168,19 @@
}
/**
+ * Returns {@code true} if the window should use stable insets. Using stable insets means that
+ * even when system bars are temporarily not visible, inset from the system bars will still be
+ * applied.
+ *
+ * NOTE: When system bars are hidden in transient mode, insets from them will not be applied
+ * even when the system bars become visible. Setting the return value to {@true} here can
+ * prevent the OverlayView from overlapping with the system bars when that happens.
+ */
+ protected boolean shouldUseStableInsets() {
+ return false;
+ }
+
+ /**
* Returns the insets types to fit to the sysui overlay window when this
* {@link OverlayViewController} is in the foreground.
*/
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewGlobalStateController.java b/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewGlobalStateController.java
index c13e486..0da2360 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewGlobalStateController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewGlobalStateController.java
@@ -108,6 +108,7 @@
if (mZOrderVisibleSortedMap.isEmpty()) {
setWindowVisible(true);
}
+
if (!(viewController instanceof OverlayPanelViewController)) {
inflateView(viewController);
}
@@ -117,6 +118,7 @@
}
updateInternalsWhenShowingView(viewController);
+ refreshUseStableInsets();
refreshInsetTypesToFit();
refreshWindowFocus();
refreshNavigationBarVisibility();
@@ -190,6 +192,7 @@
mZOrderVisibleSortedMap.remove(mZOrderMap.get(viewController));
refreshHighestZOrderWhenHidingView(viewController);
+ refreshUseStableInsets();
refreshInsetTypesToFit();
refreshWindowFocus();
refreshNavigationBarVisibility();
@@ -247,6 +250,11 @@
setWindowFocusable(mHighestZOrder == null ? false : mHighestZOrder.shouldFocusWindow());
}
+ private void refreshUseStableInsets() {
+ mSystemUIOverlayWindowController.setUsingStableInsets(
+ mHighestZOrder == null ? false : mHighestZOrder.shouldUseStableInsets());
+ }
+
private void refreshInsetTypesToFit() {
if (mZOrderVisibleSortedMap.isEmpty()) {
setFitInsetsTypes(statusBars());
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/window/SystemUIOverlayWindowController.java b/packages/CarSystemUI/src/com/android/systemui/car/window/SystemUIOverlayWindowController.java
index 8873293..b22de84 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/window/SystemUIOverlayWindowController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/window/SystemUIOverlayWindowController.java
@@ -53,6 +53,7 @@
private boolean mIsAttached = false;
private boolean mVisible = false;
private boolean mFocusable = false;
+ private boolean mUsingStableInsets = false;
@Inject
public SystemUIOverlayWindowController(
@@ -115,6 +116,7 @@
/** Sets the types of insets to fit. Note: This should be rarely used. */
public void setFitInsetsTypes(@WindowInsets.Type.InsetsType int types) {
mLpChanged.setFitInsetsTypes(types);
+ mLpChanged.setFitInsetsIgnoringVisibility(mUsingStableInsets);
updateWindow();
}
@@ -159,6 +161,10 @@
return mFocusable;
}
+ protected void setUsingStableInsets(boolean useStableInsets) {
+ mUsingStableInsets = useStableInsets;
+ }
+
private void updateWindow() {
if (mLp != null && mLp.copyFrom(mLpChanged) != 0) {
if (isAttached()) {
diff --git a/packages/InputDevices/res/raw/keyboard_layout_turkish_f.kcm b/packages/InputDevices/res/raw/keyboard_layout_turkish_f.kcm
new file mode 100644
index 0000000..5b96da0
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_turkish_f.kcm
@@ -0,0 +1,366 @@
+# Copyright (C) 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#
+# Turkish F keyboard layout.
+#
+
+type OVERLAY
+
+map key 12 SLASH
+map key 13 MINUS
+map key 43 COMMA
+map key 51 EQUALS
+map key 52 BACKSLASH
+map key 53 PERIOD
+map key 86 PLUS
+
+### ROW 1
+
+key GRAVE {
+ label: '+'
+ base: '+'
+ shift: '*'
+ ralt: '\u00ac'
+}
+
+key 1 {
+ label: '1'
+ base: '1'
+ shift: '!'
+ ralt: '\u00b9'
+}
+
+key 2 {
+ label: '2'
+ base: '2'
+ shift: '"'
+ ralt: '\u00b2'
+}
+
+key 3 {
+ label: '3'
+ base: '3'
+ shift: '^'
+ ralt: '#'
+}
+
+key 4 {
+ label: '4'
+ base: '4'
+ shift: '$'
+ ralt: '\u00bc'
+}
+
+key 5 {
+ label: '5'
+ base: '5'
+ shift: '%'
+ ralt: '\u00bd'
+}
+
+key 6 {
+ label: '6'
+ base: '6'
+ shift: '&'
+ ralt: '\u00be'
+}
+
+key 7 {
+ label: '7'
+ base: '7'
+ shift: '\''
+ ralt: '{'
+}
+
+key 8 {
+ label: '8'
+ base: '8'
+ shift: '('
+ ralt: '['
+}
+
+key 9 {
+ label: '9'
+ base: '9'
+ shift: ')'
+ ralt: ']'
+}
+
+key 0 {
+ label: '0'
+ base: '0'
+ shift: '='
+ ralt: '}'
+}
+
+key SLASH {
+ label: '/'
+ base: '/'
+ shift: '?'
+ ralt: '\\'
+}
+
+key MINUS {
+ label: '-'
+ base: '-'
+ shift: '_'
+ ralt: '|'
+}
+
+### ROW 2
+
+key Q {
+ label: 'F'
+ base: 'f'
+ shift, capslock: 'F'
+ ralt: '@'
+}
+
+key W {
+ label: 'G'
+ base: 'g'
+ shift, capslock: 'G'
+}
+
+key E {
+ label: '\u011f'
+ base: '\u011f'
+ shift, capslock: '\u011e'
+}
+
+key R {
+ label: '\u0131'
+ base: '\u0131'
+ shift, capslock: 'I'
+ ralt: '\u00b6'
+ ralt+shift, ralt+capslock: '\u00ae'
+}
+
+key T {
+ label: 'O'
+ base: 'o'
+ shift, capslock: 'O'
+}
+
+key Y {
+ label: 'D'
+ base: 'd'
+ shift, capslock: 'D'
+ ralt: '\u00a5'
+}
+
+key U {
+ label: 'R'
+ base: 'r'
+ shift, capslock: 'R'
+}
+
+key I {
+ label: 'N'
+ base: 'n'
+ shift, capslock: 'N'
+}
+
+key O {
+ label: 'H'
+ base: 'h'
+ shift, capslock: 'H'
+ ralt: '\u00f8'
+ ralt+shift, ralt+capslock: '\u00d8'
+}
+
+key P {
+ label: 'P'
+ base: 'p'
+ shift, capslock: 'P'
+ ralt: '\u00a3'
+}
+
+key LEFT_BRACKET {
+ label: 'Q'
+ base: 'q'
+ shift, capslock: 'Q'
+ ralt: '"'
+}
+
+key RIGHT_BRACKET {
+ label: 'W'
+ base: 'w'
+ shift, capslock: 'W'
+ ralt: '~'
+}
+
+### ROW 3
+
+key A {
+ label: '\u0075'
+ base: '\u0075'
+ shift, capslock: '\u0055'
+ ralt: '\u00e6'
+ ralt+shift, ralt+capslock: '\u00c6'
+}
+
+key S {
+ label: 'i'
+ base: 'i'
+ shift, capslock: '\u0130'
+ ralt: '\u00df'
+ ralt+shift, ralt+capslock: '\u00a7'
+}
+
+key D {
+ label: 'E'
+ base: 'e'
+ shift, capslock: 'E'
+ ralt: '\u20ac'
+}
+
+key F {
+ label: 'A'
+ base: 'a'
+ shift, capslock: 'A'
+ ralt: '\u00aa'
+}
+
+key G {
+ label: '\u00fc'
+ base: '\u00fc'
+ shift, capslock: '\u00dc'
+}
+
+key H {
+ label: 'T'
+ base: 't'
+ shift, capslock: 'T'
+ ralt: '\u20ba'
+}
+
+key J {
+ label: 'K'
+ base: 'k'
+ shift, capslock: 'K'
+}
+
+key K {
+ label: 'M'
+ base: 'm'
+ shift, capslock: 'M'
+}
+
+key L {
+ label: 'L'
+ base: 'l'
+ shift, capslock: 'L'
+}
+
+key SEMICOLON {
+ label: 'Y'
+ base: 'y'
+ shift, capslock: 'Y'
+ ralt: '\u00b4'
+}
+
+key APOSTROPHE {
+ label: '\u015f'
+ base: '\u015f'
+ shift, capslock: '\u015e'
+}
+
+key COMMA {
+ label: 'X'
+ base: 'x'
+ shift: 'X'
+ ralt: '\u0060'
+}
+
+### ROW 4
+
+key PLUS {
+ label: '<'
+ base: '<'
+ shift: '>'
+ ralt: '|'
+ ralt+shift, ralt+capslock: '\u00a6'
+}
+
+key Z {
+ label: 'J'
+ base: 'j'
+ shift, capslock: 'J'
+ ralt: '\u00ab'
+ ralt+shift, ralt+capslock: '<'
+}
+
+key X {
+ label: '\u00f6'
+ base: '\u00f6'
+ shift, capslock: '\u00d6'
+ ralt: '\u00bb'
+ ralt+shift, ralt+capslock: '>'
+}
+
+key C {
+ label: 'V'
+ base: 'v'
+ shift, capslock: 'V'
+ ralt: '\u00a2'
+ ralt+shift, ralt+capslock: '\u00a9'
+}
+
+key V {
+ label: 'C'
+ base: 'c'
+ shift, capslock: 'C'
+}
+
+key B {
+ label: '\u00e7'
+ base: '\u00e7'
+ shift, capslock: '\u00c7'
+}
+
+key N {
+ label: 'Z'
+ base: 'z'
+ shift, capslock: 'Z'
+}
+
+key M {
+ label: 'S'
+ base: 's'
+ shift, capslock: 'S'
+ ralt: '\u00b5'
+ ralt+shift, ralt+capslock: '\u00ba'
+}
+
+key EQUALS {
+ label: 'B'
+ base: 'b'
+ shift, capslock: 'B'
+ ralt: '\u00d7'
+}
+
+key BACKSLASH {
+ label: '.'
+ base: '.'
+ shift, capslock: ':'
+ ralt: '\u00f7'
+}
+
+key PERIOD {
+ label: ','
+ base: ','
+ shift: ';'
+}
diff --git a/packages/InputDevices/res/values/strings.xml b/packages/InputDevices/res/values/strings.xml
index 9d068fe..1e13940 100644
--- a/packages/InputDevices/res/values/strings.xml
+++ b/packages/InputDevices/res/values/strings.xml
@@ -105,6 +105,9 @@
<!-- Turkish keyboard layout label. [CHAR LIMIT=35] -->
<string name="keyboard_layout_turkish">Turkish</string>
+ <!-- Turkish keyboard layout label. [CHAR LIMIT=35] -->
+ <string name="keyboard_layout_turkish_f">Turkish F</string>
+
<!-- Ukrainian keyboard layout label. [CHAR LIMIT=35] -->
<string name="keyboard_layout_ukrainian">Ukrainian</string>
diff --git a/packages/InputDevices/res/xml/keyboard_layouts.xml b/packages/InputDevices/res/xml/keyboard_layouts.xml
index 6b78b68..976a279 100644
--- a/packages/InputDevices/res/xml/keyboard_layouts.xml
+++ b/packages/InputDevices/res/xml/keyboard_layouts.xml
@@ -132,6 +132,10 @@
android:label="@string/keyboard_layout_turkish"
android:keyboardLayout="@raw/keyboard_layout_turkish" />
+ <keyboard-layout android:name="keyboard_layout_turkish_f"
+ android:label="@string/keyboard_layout_turkish_f"
+ android:keyboardLayout="@raw/keyboard_layout_turkish_f" />
+
<keyboard-layout android:name="keyboard_layout_ukrainian"
android:label="@string/keyboard_layout_ukrainian"
android:keyboardLayout="@raw/keyboard_layout_ukrainian" />
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 6751fa4..2f97f27 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Voordat jy \'n beperkte profiel kan skep, moet jy \'n skermslot opstel om jou programme en persoonlike data te beskerm."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Stel slot op"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Skakel oor na <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Voeg gas by"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Verwyder gas"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Gas"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Toestelverstek"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Gedeaktiveer"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Geaktiveer"</string>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 470e780..f0d8a40 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"የተገደበ መገለጫ መፍጠር ከመቻልዎ በፊት መተግበሪያዎችዎን እና የግል ውሂብዎን ለመጠበቅ ቁልፍ ማያ ገጽ ማዋቀር አለብዎት።"</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"ቁልፍ አዘጋጅ"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"ወደ <xliff:g id="USER_NAME">%s</xliff:g> ቀይር"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"እንግዳን አክል"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"እንግዳን አስወግድ"</string>
<string name="guest_nickname" msgid="6332276931583337261">"እንግዳ"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"የመሣሪያ ነባሪ"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"ተሰናክሏል"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"ነቅቷል"</string>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 0b45380..323ba44 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -549,9 +549,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"قبل أن تتمكن من إنشاء ملف شخصي مقيد، يلزمك إعداد تأمين للشاشة لحماية تطبيقاتك وبياناتك الشخصية."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"تعيين التأمين"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"التبديل إلى <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"إضافة ضيف"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"إزالة جلسة الضيف"</string>
<string name="guest_nickname" msgid="6332276931583337261">"ضيف"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"الإعداد التلقائي للجهاز"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"غير مفعّل"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"مفعّل"</string>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index f993dba..7679c64 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"আপুনি সীমিত প্ৰ\'ফাইল এটা সৃষ্টি কৰাৰ আগেয়ে, আপোনাৰ ব্যক্তিগত ডেটা আৰু এপবিলাকক সুৰক্ষিত কৰিবলৈ স্ক্ৰীণ লক এটা নিৰ্ধাৰণ কৰিব লাগিব।"</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"লক ছেট কৰক"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g>লৈ সলনি কৰক"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"অতিথি যোগ কৰক"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"অতিথি আঁতৰাওক"</string>
<string name="guest_nickname" msgid="6332276931583337261">"অতিথি"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"ডিভাইচ ডিফ’ল্ট"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"অক্ষম কৰা আছে"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"সক্ষম কৰা আছে"</string>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index 6a50661..d0bf0ed 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Məhdudlaşdırılmış profil yaratmadan öncə, Siz tətbiqlərinizi və şəxsi datanızı qorumaq üçün ekran kilidi quraşdırmalısınız."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Kilid ayarlayın"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> adlı istifadəçiyə keçin"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Qonaq əlavə edin"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Qonağı silin"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Qonaq"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Cihaz defoltu"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Deaktiv"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Aktiv"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index cf988ab..3beb9b84 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -546,9 +546,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Da biste mogli da napravite ograničeni profil, treba da podesite zaključavanje ekrana da biste zaštitili aplikacije i lične podatke."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Podesi zaključavanje"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Pređi na korisnika <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Dodaj gosta"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Ukloni gosta"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Gost"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Podrazumevano za uređaj"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Onemogućeno"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Omogućeno"</string>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 7f6237d..af6da4e 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -547,9 +547,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Перш чым вы зможаце стварыць профіль з абмежаваннямi, вам трэба наладзіць блакiроўку экрана для абароны сваiх дадаткаў і асабістай інфармацыі."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Усталёўка блакiроўкi"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Пераключыцца на карыстальніка <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Дадаць госця"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Выдаліць госця"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Госць"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Стандартная прылада"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Выключана"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Уключана"</string>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 747cb26..0097c9c 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Преди да можете да създадете потребителски профил с ограничена функционалност, трябва да настроите заключения екран, за да защитите приложенията и личните си данни."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Задаване на заключване"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Превключване към <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Добавяне на гост"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Премахване на госта"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Гост"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Стандартна настройка за у-вото"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Деактивирано"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Активирано"</string>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index 1ab88ed..c351542 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"আপনি একটি সীমাবদ্ধযুক্ত প্রোফাইল তৈরি করার আগে, আপনাকে আপনার অ্যাপ্লিকেশন এবং ব্যক্তিগত ডেটা সুরক্ষিত করার জন্য একটি স্ক্রিন লক সেট-আপ করতে হবে।"</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"লক সেট করুন"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g>-এ পাল্টান"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"অতিথি যোগ করুন"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"অতিথি সরান"</string>
<string name="guest_nickname" msgid="6332276931583337261">"অতিথি"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"ডিভাইসের ডিফল্ট"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"বন্ধ করা আছে"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"চালু করা আছে"</string>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index e329c99..3d358730 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -546,9 +546,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Prije nego vam se omogući kreiranje ograničenog profila, morate postaviti zaključavanje ekrana da biste zaštitili svoje aplikacije i lične podatke."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Postaviti zaključavanje"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Prebaci na korisnika <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Dodaj gosta"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Ukloni gosta"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Gost"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Zadana postavka uređaja"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Onemogućeno"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Omogućeno"</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 5ffdacd..b1edd78 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Per crear un perfil restringit, has de configurar una pantalla de bloqueig per protegir les aplicacions i les dades personals."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Defineix un bloqueig"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Canvia a <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Afegeix un convidat"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Suprimeix el convidat"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Convidat"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Opció predeter. del dispositiu"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Desactivat"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Activat"</string>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 0aef99f..bdce444c 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -547,9 +547,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Před vytvořením omezeného profilu je nutné nejprve nastavit zámek obrazovky k ochraně aplikací a dat."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Nastavit zámek"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Přepnout na uživatele <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Přidat hosta"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Odstranit hosta"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Host"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Výchozí nastavení zařízení"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Vypnuto"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Zapnuto"</string>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 98068cb..1dc0e4e 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Før du kan oprette en begrænset profil, skal du oprette en skærmlås for at beskytte dine apps og personlige data."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Konfigurer låseskærmen"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Skift til <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Tilføj gæsten"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Fjern gæsten"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Gæst"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Enhedens standardindstilling"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Deaktiveret"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Aktiveret"</string>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 0837ad3..a9cdf1f 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Vor dem Erstellen eines eingeschränkten Profils musst du eine Displaysperre einrichten, um deine Apps und personenbezogenen Daten zu schützen."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Sperre einrichten"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Zu <xliff:g id="USER_NAME">%s</xliff:g> wechseln"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Gast hinzufügen"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Gast entfernen"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Gast"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Gerätestandard"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Deaktiviert"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Aktiviert"</string>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index 1f9d977..00b8434 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Προκειμένου να μπορέσετε να δημιουργήσετε ένα περιορισμένο προφίλ, θα πρέπει να δημιουργήσετε ένα κλείδωμα οθόνης για την προστασία των εφαρμογών και των προσωπικών δεδομένων σας."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Ορισμός κλειδώματος"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Εναλλαγή σε <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Προσθήκη επισκέπτη"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Κατάργηση επισκέπτη"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Επισκέπτης"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Προεπιλογή συσκευής"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Ανενεργή"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Ενεργή"</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index abe61a9..4bb2d8a 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Before you can create a restricted profile, you\'ll need to set up a screen lock to protect your apps and personal data."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Set lock"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Switch to <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Add guest"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Remove guest"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Guest"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Device default"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Disabled"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Enabled"</string>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index 959ad46..05c12d6 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Before you can create a restricted profile, you\'ll need to set up a screen lock to protect your apps and personal data."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Set lock"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Switch to <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Add guest"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Remove guest"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Guest"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Device default"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Disabled"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Enabled"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index abe61a9..4bb2d8a 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Before you can create a restricted profile, you\'ll need to set up a screen lock to protect your apps and personal data."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Set lock"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Switch to <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Add guest"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Remove guest"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Guest"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Device default"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Disabled"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Enabled"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index abe61a9..4bb2d8a 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Before you can create a restricted profile, you\'ll need to set up a screen lock to protect your apps and personal data."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Set lock"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Switch to <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Add guest"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Remove guest"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Guest"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Device default"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Disabled"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Enabled"</string>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index 738dd2a..699ad42 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -545,9 +545,14 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Before you can create a restricted profile, you’ll need to set up a screen lock to protect your apps and personal data."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Set lock"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Switch to <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Creating new user…"</string>
+ <string name="user_nickname" msgid="262624187455825083">"Nickname"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Add guest"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Remove guest"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Guest"</string>
+ <string name="user_image_take_photo" msgid="467512954561638530">"Take a photo"</string>
+ <string name="user_image_choose_photo" msgid="1363820919146782908">"Choose an image"</string>
+ <string name="user_image_photo_selector" msgid="433658323306627093">"Select photo"</string>
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Device default"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Disabled"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Enabled"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index d1e4fb5..1dc5f5b 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Para poder crear un perfil restringido, debes configurar un bloqueo de pantalla que proteja tus aplicaciones y datos personales."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Configurar bloqueo"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Cambiar a <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Agregar invitado"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Quitar invitado"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Invitado"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Predeterminado del dispositivo"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Inhabilitado"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Habilitado"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 9ad71e2..977b469 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Para poder crear un perfil restringido, debes configurar una pantalla de bloqueo que proteja tus aplicaciones y datos personales."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Establecer bloqueo"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Cambiar a <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Añadir invitado"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Quitar invitado"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Invitado"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Predeterminado por el dispositivo"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Inhabilitado"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Habilitado"</string>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index 14d3b57..3c2593a 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Enne piiratud profiili loomist peate seadistama lukustusekraani, et oma rakendusi ja isiklikke andmeid kaitsta."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Määra lukk"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Lülita kasutajale <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Lisa külaline"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Eemalda külaline"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Külaline"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Seadme vaikeseade"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Keelatud"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Lubatud"</string>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 4a11aa7..33ce3c7 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Profil murriztua sortu aurretik, aplikazioak eta datu pertsonalak babesteko, pantaila blokeatzeko metodo bat konfiguratu beharko duzu."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Ezarri blokeoa"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Aldatu <xliff:g id="USER_NAME">%s</xliff:g> erabiltzailera"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Gehitu gonbidatua"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Kendu gonbidatua"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Gonbidatua"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Gailuaren balio lehenetsia"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Desgaituta"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Gaituta"</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 3373f81..0453788 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"قبل از ایجاد یک نمایه محدود، باید یک قفل صفحه را برای محافظت از برنامهها و دادههای شخصی خود تنظیم کنید."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"تنظیم قفل"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"رفتن به <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"افزودن مهمان"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"حذف مهمان"</string>
<string name="guest_nickname" msgid="6332276931583337261">"مهمان"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"پیشفرض دستگاه"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"غیرفعال"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"فعال"</string>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 3d28f1d..7f85572 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Ennen kuin voit luoda rajoitetun profiilin, määritä näytön lukitus, joka suojelee sovelluksiasi ja henkilökohtaisia tietojasi."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Aseta lukitus"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Vaihda tähän käyttäjään: <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Lisää vieras"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Poista vieras"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Vieras"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Laitteen oletusasetus"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Ei käytössä"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Käytössä"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index 87d3de1..1745e02 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Avant de créer un profil limité, vous devez définir un écran de verrouillage pour protéger vos applications et vos données personnelles."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Définir verrouillage écran"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Passer à <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Ajouter un invité"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Supprimer l\'invité"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Invité"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Valeur par défaut de l\'appareil"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Désactivé"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Activé"</string>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 5f5be97..8c753ae 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Avant de créer un profil limité, vous devez définir un écran de verrouillage pour protéger vos applications et vos données personnelles."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Définir verrouillage écran"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Passer à <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Ajouter un invité"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Supprimer l\'invité"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Invité"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Paramètre par défaut"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Désactivé"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Activé"</string>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index af43099..414564b 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Para poder crear un perfil restrinxido, precisarás configurar un bloqueo da pantalla para protexer as túas aplicacións e datos persoais."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Establecer bloqueo"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Cambiar a <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Engadir convidado"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Quitar convidado"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Convidado"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Funcionamento predeterminado"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Desactivado"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Activado"</string>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index 894a14a..634870c 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"તમે પ્રતિબંધિત પ્રોફાઇલ બનાવી શકો તે પહેલાં, તમારે તમારી ઍપ્લિકેશનો અને વ્યક્તિગત ડેટાની સુરક્ષા માટે એક લૉક સ્ક્રીન સેટ કરવાની જરૂર પડશે."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"લૉક સેટ કરો"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> પર સ્વિચ કરો"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"અતિથિ ઉમેરો"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"અતિથિને કાઢી નાખો"</string>
<string name="guest_nickname" msgid="6332276931583337261">"અતિથિ"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"ડિવાઇસ ડિફૉલ્ટ"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"બંધ છે"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"ચાલુ છે"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 6e734bc..bd052c0 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"इससे पहले कि आप कोई प्रतिबंधित प्रोफ़ाइल बनाएं, आपको अपने ऐप्लिकेशन और व्यक्तिगत डेटा की सुरक्षा करने के लिए एक स्क्रीन लॉक सेट करना होगा."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"लॉक सेट करें"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> पर जाएं"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"मेहमान जोड़ें"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"मेहमान हटाएं"</string>
<string name="guest_nickname" msgid="6332276931583337261">"मेहमान"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"डिवाइस की डिफ़ॉल्ट सेटिंग"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"बंद है"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"चालू है"</string>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 3edc452..3cff480 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -546,9 +546,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Prije izrade ograničenog profila trebate postaviti zaključavanje zaslona radi zaštite svojih aplikacija i osobnih podataka."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Postavi zaključavanje"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Prelazak na korisnika <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Dodavanje gosta"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Uklanjanje gosta"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Gost"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Zadana postavka uređaja"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Onemogućeno"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Omogućeno"</string>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index d86d88b..854265c 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Mielőtt létrehozhatna egy korlátozott profilt, be kell állítania egy képernyőzárat, hogy megvédje alkalmazásait és személyes adatait."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Képernyőzár beállítása"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Váltás erre: <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Vendég hozzáadása"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Vendég munkamenet eltávolítása"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Vendég"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Alapértelmezett"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Letiltva"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Engedélyezve"</string>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index e434cac..35b218e 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Նախքան դուք կկարողանաք ստեղծել սահմանափակ պրոֆիլ, դուք պետք է կարգավորեք էկրանի կողպումը` ձեր ծրագրերը և անձնական տվյալները պաշտպանելու համար:"</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Կարգավորել կողպումը"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Անցնել <xliff:g id="USER_NAME">%s</xliff:g> պրոֆիլին"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Ավելացնել հյուր"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Հեռացնել հյուրին"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Հյուր"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Կանխադրված տարբերակ"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Անջատված է"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Միացված է"</string>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index a6f8846..cf6455f 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -156,7 +156,7 @@
<string name="launch_defaults_none" msgid="8049374306261262709">"Tidak ada setelan default"</string>
<string name="tts_settings" msgid="8130616705989351312">"Setelan text-to-speech"</string>
<string name="tts_settings_title" msgid="7602210956640483039">"Keluaran text-to-speech"</string>
- <string name="tts_default_rate_title" msgid="3964187817364304022">"Laju bicara"</string>
+ <string name="tts_default_rate_title" msgid="3964187817364304022">"Kecepatan ucapan"</string>
<string name="tts_default_rate_summary" msgid="3781937042151716987">"Kecepatan teks diucapkan"</string>
<string name="tts_default_pitch_title" msgid="6988592215554485479">"Tinggi nada"</string>
<string name="tts_default_pitch_summary" msgid="9132719475281551884">"Memengaruhi nada ucapan yang disintesis"</string>
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Sebelum dapat membuat profil yang dibatasi, Anda perlu menyiapkan kunci layar untuk melindungi aplikasi dan data pribadi Anda."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Setel kunci"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Beralih ke <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Tambahkan tamu"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Hapus tamu"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Tamu"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Default perangkat"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Nonaktif"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Aktif"</string>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index caf2323..b4be963 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Áður en þú getur búið til takmarkað snið þarftu að setja upp skjálás til að vernda forritin þín og persónuleg gögn."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Velja lás"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Skipta yfir í <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Bæta gesti við"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Fjarlægja gest"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Gestur"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Sjálfgefin stilling tækis"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Slökkt"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Virkt"</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 8d18727..69b1b5e 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Prima di poter creare un profilo con limitazioni, devi impostare un blocco schermo per proteggere le tue app e i tuoi dati personali."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Imposta blocco"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Passa a <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Aggiungi ospite"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Rimuovi ospite"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Ospite"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Parametro predefinito"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Non attivo"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Attivo"</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index fff881c..158872d 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -547,9 +547,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"לפני שתוכל ליצור פרופיל מוגבל, תצטרך להגדיר נעילת מסך כדי להגן על האפליקציות ועל הנתונים האישיים שלך."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"הגדרת נעילה"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"מעבר אל <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"הוספת אורח"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"הסרת אורח"</string>
<string name="guest_nickname" msgid="6332276931583337261">"אורח"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"ברירת המחדל של המכשיר"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"מושבת"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"מופעל"</string>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 5e579b7..13fd53f 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"制限付きプロファイルを作成する場合は、アプリや個人データを保護するように画面ロックを設定しておく必要があります。"</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"ロックを設定"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> に切り替え"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"ゲストを追加"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"ゲストを削除"</string>
<string name="guest_nickname" msgid="6332276931583337261">"ゲスト"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"デバイスのデフォルト"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"無効"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"有効"</string>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index 1b5fae9..8302b8d 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -545,9 +545,14 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"შეზღუდული პროფილის შექმნამდე, საკუთარი აპლიკაციებისა და პირადი მონაცემების დასაცავად, უნდა დაბლოკოთ ეკრანი."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"საკეტის დაყენება"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g>-ზე გადართვა"</string>
+ <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"მიმდინარეობს ახალი მომხმარებლის შექმნა…"</string>
+ <string name="user_nickname" msgid="262624187455825083">"მეტსახელი"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"სტუმრის დამატება"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"სტუმრის ამოშლა"</string>
<string name="guest_nickname" msgid="6332276931583337261">"სტუმარი"</string>
+ <string name="user_image_take_photo" msgid="467512954561638530">"ფოტოს გადაღება"</string>
+ <string name="user_image_choose_photo" msgid="1363820919146782908">"აირჩიეთ სურათი"</string>
+ <string name="user_image_photo_selector" msgid="433658323306627093">"ფოტოს არჩევა"</string>
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"მოწყობილობის ნაგულისხმევი"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"გათიშული"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"ჩართული"</string>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index 9c290e9..f411d00 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Шектелген профайл жасақтауға дейін қолданбалар мен жеке деректерді қорғау үшін экран бекітпесін тағайындау қажет."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Бекітпе тағайындау"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> пайдаланушысына ауысу"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Қонақты енгізу"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Қонақты өшіру"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Қонақ"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Құрылғыны әдепкісінше реттеу"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Өшірулі"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Қосулы"</string>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 2878db1..9b7cc4c 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"មុនពេលអ្នកអាចបង្កើតប្រវត្តិរូបបានដាក់កម្រិត អ្នកត្រូវរៀបចំការចាក់សោអេក្រង់ ដើម្បីការពារកម្មវិធី និងទិន្នន័យផ្ទាល់ខ្លួនរបស់អ្នក។"</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"កំណត់ការចាក់សោ"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"ប្ដូរទៅ <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"បញ្ចូលភ្ញៀវ"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"លុបភ្ញៀវ"</string>
<string name="guest_nickname" msgid="6332276931583337261">"ភ្ញៀវ"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"លំនាំដើមរបស់ឧបករណ៍"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"បានបិទ"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"បានបើក"</string>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 7b01056..1f74d9b6 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"ನೀವು ನಿರ್ಬಂಧಿತ ಪ್ರೊಫೈಲ್ ಅನ್ನು ರಚಿಸಬಹುದಾದರ ಮೊದಲು, ನಿಮ್ಮ ಅಪ್ಲಿಕೇಶನ್ಗಳು ಮತ್ತು ವೈಯಕ್ತಿಕ ಡೇಟಾವನ್ನು ರಕ್ಷಿಸಲು ನೀವು ಪರದೆಯ ಲಾಕ್ ಹೊಂದಿಸುವ ಅಗತ್ಯವಿದೆ."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"ಲಾಕ್ ಹೊಂದಿಸಿ"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> ಗೆ ಬದಲಿಸಿ"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"ಅತಿಥಿಯನ್ನು ಸೇರಿಸಿ"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"ಅತಿಥಿಯನ್ನು ತೆಗೆದುಹಾಕಿ"</string>
<string name="guest_nickname" msgid="6332276931583337261">"ಅತಿಥಿ"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"ಸಾಧನದ ಡೀಫಾಲ್ಟ್"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index f13d9b8..d130834 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"제한된 프로필을 만들기 전에 화면 잠금을 설정하여 앱과 개인 데이터를 보호해야 합니다."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"잠금 설정"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g>(으)로 전환"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"게스트 추가"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"게스트 삭제"</string>
<string name="guest_nickname" msgid="6332276931583337261">"게스트"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"기기 기본값"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"사용 중지됨"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"사용 설정됨"</string>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 419c18f..5672913 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Чектелген профайл түзөөрдөн мурун, сиз өзүңүздүн колдонмолоруңузду жана жеке маалыматтарыңызды коргош үчүн, бөгөттөө көшөгөсүн орнотушуңуз керек болот."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Бөгөт коюу"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> аккаунтуна которулуу"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Конок кошуу"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Конокту өчүрүү"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Конок"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Түзмөктүн демейки параметри"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Өчүк"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Күйүк"</string>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index a72861e..b3b3c81 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"ກ່ອນທ່ານຈະສ້າງໂປຣໄຟລ໌ທີ່ຖືກຈຳກັດນັ້ນ, ທ່ານຈະຕ້ອງຕັ້ງຄ່າການລັອກໜ້າຈໍ ເພື່ອປ້ອງກັນແອັບຯ ແລະຂໍ້ມູນສ່ວນໂຕຂອງທ່ານກ່ອນ."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"ຕັ້ງການລັອກ"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"ສະຫຼັບໄປ <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"ເພີ່ມແຂກ"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"ລຶບແຂກອອກ"</string>
<string name="guest_nickname" msgid="6332276931583337261">"ແຂກ"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"ຄ່າເລີ່ມຕົ້ນອຸປະກອນ"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"ປິດການນຳໃຊ້ແລ້ວ"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"ເປີດການນຳໃຊ້ແລ້ວ"</string>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index c72bf21..2e5385e 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -547,9 +547,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Prieš kuriant apribotą profilį reikės nustatyti ekrano užraktą, kad apsaugotumėte programas ir asmeninius duomenis."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Nustatyti užraktą"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Perjungti į <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Pridėti svečią"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Pašalinti svečią"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Svečias"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Numatyt. įrenginio nustatymas"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Išjungta"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Įgalinta"</string>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index d95e57d..f4fe8e3 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -546,9 +546,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Lai varētu izveidot ierobežotu profilu, jums jāiestata ekrāna bloķēšana, kas aizsargās jūsu lietotni un personas datus."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Iestatīt bloķēšanu"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Pārslēgties uz: <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Pievienot viesi"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Noņemt viesi"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Viesis"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Ierīces noklusējums"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Atspējots"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Iespējots"</string>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index 58d4af1..1e933fb 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Пред да може да создадете ограничен профил, треба да поставите заклучување на екранот за да ги заштити вашите апликации и лични податоци."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Постави заклучување"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Префрли на <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Додај гостин"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Отстрани гостин"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Гостин"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Стандардно за уредот"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Оневозможено"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Овозможено"</string>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 3c281c8..970f778 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"ഒരു നിയന്ത്രിത പ്രൊഫൈൽ സൃഷ്ടിക്കുന്നതിനുമുമ്പ്, നിങ്ങളുടെ അപ്ലിക്കേഷനുകളും വ്യക്തിഗത ഡാറ്റയും പരിരക്ഷിക്കുന്നതിന് ഒരു സ്ക്രീൻ ലോക്ക് സജ്ജീകരിക്കേണ്ടതുണ്ട്."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"ലോക്ക് സജ്ജീകരിക്കുക"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> എന്നതിലേക്ക് മാറുക"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"അതിഥിയെ ചേർക്കുക"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"അതിഥിയെ നീക്കം ചെയ്യുക"</string>
<string name="guest_nickname" msgid="6332276931583337261">"അതിഥി"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"ഉപകരണത്തിന്റെ ഡിഫോൾട്ട് പ്രവർത്തനം"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"പ്രവർത്തനരഹിതമാക്കി"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"പ്രവർത്തനക്ഷമമാക്കി"</string>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index 37fc5b4..3dc4989 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Та хязгаарлагдсан профайл үүсгэхийн өмнө өөрийн апп-ууд болон хувийн өгөгдлийг хамгаалахын тулд дэлгэцийн түгжээг тохируулах шаардлагатай."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Түгжээг тохируулах"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> руу сэлгэх"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Зочин нэмэх"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Зочин хасах"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Зочин"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Төхөөрөмжийн өгөгдмөл"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Идэвхгүй болгосон"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Идэвхжүүлсэн"</string>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 360f158..7e418a4 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"तुम्ही एक प्रतिबंधित प्रोफाईल तयार करु शकण्यापूर्वी तुम्हाला तुमचे अॅप्स आणि वैयक्तिक डेटा संरक्षित करण्यासाठी एक स्क्रीन लॉक सेट करण्याची आवश्यकता राहील."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"लॉक सेट करा"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> वर स्विच करा"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"अतिथी जोडा"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"अतिथी काढून टाका"</string>
<string name="guest_nickname" msgid="6332276931583337261">"अतिथी"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"डिव्हाइस डीफॉल्ट"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"बंद केले आहे"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"सुरू केले आहे"</string>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index 68356df2..4c23a84 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Sebelum anda boleh membuat profil yang terhad, anda perlu menyediakan kunci skrin untuk melindungi apl dan data peribadi anda."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Tetapkan kunci"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Tukar kepada <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Tambah tetamu"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Alih keluar tetamu"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Tetamu"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Lalai peranti"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Dilumpuhkan"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Didayakan"</string>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index 3729a83..aa3cf08 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"ကန့်သတ်ကိုယ်ရေးအချက်အလက်တစ်ခုကို မပြုလုပ်မီ သင်၏ အပလီကေးရှင်းများနှင့် ကိုယ်ပိုင်အချက်အလက်များကို ကာကွယ်ရန် မျက်နှာပြင်သော့ချခြင်းကို စီမံရန် လိုအပ်လိမ့်မည်"</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"သော့ချရန် သတ်မှတ်ပါ"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> သို့ ပြောင်းရန်"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"ဧည့်သည့် ထည့်ရန်"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"ဧည့်သည်ကို ဖယ်ထုတ်ရန်"</string>
<string name="guest_nickname" msgid="6332276931583337261">"ဧည့်သည်"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"စက်ပစ္စည်းမူရင်း"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"ပိတ်ထားသည်"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"ဖွင့်ထားသည်"</string>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 0e0e761..0c5431b 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Før du kan opprette en begrenset profil, må du konfigurere skjermlåsen for å beskytte appene og de personlige dataene dine."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Angi lås"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Bytt til <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Legg til en gjest"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Fjern gjesten"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Gjest"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Standard for enheten"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Slått av"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Slått på"</string>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index ee368fd..4c230d3 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"निषेधयुक्त प्रोफाइल बनाउनु अघि तपाईँको एप र व्यक्तिगत डेटा सुरक्षा गर्नाका लागि तपाईँले स्क्रिन लक सेटअप गर्नु पर्दछ ।"</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"लक सेट गर्नुहोस्"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"प्रयोगकर्ता बदलेर <xliff:g id="USER_NAME">%s</xliff:g> पार्नुहोस्"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"अतिथि थप्नुहोस्"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"अतिथि हटाउनुहोस्"</string>
<string name="guest_nickname" msgid="6332276931583337261">"अतिथि"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"पूर्वनिर्धारित यन्त्र"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"असक्षम पारिएको छ"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"सक्षम पारिएको छ"</string>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 27f5dc9..ae734a5 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Voordat je een beperkt profiel kunt maken, moet je een schermvergrendeling instellen om je apps en persoonsgegevens te beschermen."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Vergrendeling instellen"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Overschakelen naar <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Gast toevoegen"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Gast verwijderen"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Gast"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Apparaatstandaard"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Uitgeschakeld"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Ingeschakeld"</string>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index d200f50..18a88fa 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"ପ୍ରତିବନ୍ଧିତ ପ୍ରୋଫାଇଲ୍ ତିଆରି କରିବାବେଳେ, ନିଜ ଆପ୍ ଓ ବ୍ୟକ୍ତିଗତ ତଥ୍ୟର ସୁରକ୍ଷା ପାଇଁ ଏକ ସ୍କ୍ରୀନ୍ ଲକ୍ ସେଟ୍ କରନ୍ତୁ।"</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"ଲକ୍ ସେଟ୍ କରନ୍ତୁ"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g>କୁ ସ୍ୱିଚ୍ କରନ୍ତୁ"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"ଅତିଥି ଯୋଗ କରନ୍ତୁ"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"ଅତିଥିଙ୍କୁ କାଢ଼ି ଦିଅନ୍ତୁ"</string>
<string name="guest_nickname" msgid="6332276931583337261">"ଅତିଥି"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"ଡିଭାଇସ୍ ଡିଫଲ୍ଟ"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"ଅକ୍ଷମ କରାଯାଇଛି"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"ସକ୍ଷମ କରାଯାଇଛି"</string>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index 354ee12..b1bde27 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"ਇਸਤੋਂ ਪਹਿਲਾਂ ਕਿ ਤੁਸੀਂ ਇੱਕ ਪ੍ਰਤਿਬੰਧਿਤ ਪ੍ਰੋਫਾਈਲ ਬਣਾ ਸਕੋ, ਤੁਹਾਨੂੰ ਆਪਣੀਆਂ ਐਪਾਂ ਅਤੇ ਨਿੱਜੀ ਡਾਟਾ ਸੁਰੱਖਿਅਤ ਕਰਨ ਲਈ ਇੱਕ ਸਕ੍ਰੀਨ ਲਾਕ ਸੈੱਟ ਅੱਪ ਕਰਨ ਦੀ ਲੋੜ ਹੈ।"</string>
<string name="user_set_lock_button" msgid="1427128184982594856">" ਲਾਕ ਸੈੱਟ ਕਰੋ"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> \'ਤੇ ਜਾਓ"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"ਮਹਿਮਾਨ ਸ਼ਾਮਲ ਕਰੋ"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"ਮਹਿਮਾਨ ਹਟਾਓ"</string>
<string name="guest_nickname" msgid="6332276931583337261">"ਮਹਿਮਾਨ"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"ਡੀਵਾਈਸ ਪੂਰਵ-ਨਿਰਧਾਰਤ"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"ਬੰਦ ਕੀਤਾ ਗਿਆ"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"ਚਾਲੂ ਕੀਤਾ ਗਿਆ"</string>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 095412c..7ea2d0c 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -547,9 +547,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Zanim utworzysz profil z ograniczeniami, musisz skonfigurować ekran blokady, by chronić aplikacje i osobiste dane."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Ustaw blokadę"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Przełącz na: <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Dodaj gościa"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Usuń gościa"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Gość"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Ustawienie domyślne urządzenia"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Wyłączono"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Włączono"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 895a987..102961a 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -545,9 +545,14 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Antes de criar um perfil restrito, configure um bloqueio de tela para proteger seus apps e seus dados pessoais."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Definir bloqueio"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Mudar para <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Criando novo usuário…"</string>
+ <string name="user_nickname" msgid="262624187455825083">"Apelido"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Adicionar convidado"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Remover convidado"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Convidado"</string>
+ <string name="user_image_take_photo" msgid="467512954561638530">"Tirar uma foto"</string>
+ <string name="user_image_choose_photo" msgid="1363820919146782908">"Escolher uma imagem"</string>
+ <string name="user_image_photo_selector" msgid="433658323306627093">"Selecionar foto"</string>
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Padrão do dispositivo"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Desativado"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Ativado"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 2d9f037..de536b2 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Antes de poder criar um perfil restrito, tem de configurar um bloqueio de ecrã para proteger as suas aplicações e dados pessoais."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Definir bloqueio"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Mudar para <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Adicionar convidado"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Remover convidado"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Convidado"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Predefinição do dispositivo"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Desativada"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Ativada"</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 895a987..102961a 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -545,9 +545,14 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Antes de criar um perfil restrito, configure um bloqueio de tela para proteger seus apps e seus dados pessoais."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Definir bloqueio"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Mudar para <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Criando novo usuário…"</string>
+ <string name="user_nickname" msgid="262624187455825083">"Apelido"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Adicionar convidado"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Remover convidado"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Convidado"</string>
+ <string name="user_image_take_photo" msgid="467512954561638530">"Tirar uma foto"</string>
+ <string name="user_image_choose_photo" msgid="1363820919146782908">"Escolher uma imagem"</string>
+ <string name="user_image_photo_selector" msgid="433658323306627093">"Selecionar foto"</string>
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Padrão do dispositivo"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Desativado"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Ativado"</string>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 728db17..934ef64 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -546,9 +546,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Înainte de a putea crea un profil cu permisiuni limitate, va trebui să configurați blocarea ecranului pentru a vă proteja aplicațiile și datele personale."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Configurați blocarea"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Treceți la <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Adăugați un invitat"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Ștergeți invitatul"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Invitat"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Prestabilit pentru dispozitiv"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Dezactivat"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Activat"</string>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index ff2115e..e75ee7f 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -547,9 +547,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Чтобы создать профиль с ограниченным доступом, необходимо предварительно настроить блокировку экрана для защиты приложений и личных данных"</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Включить блокировку"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Переключиться на этот аккаунт: <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Добавить аккаунт гостя"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Удалить аккаунт гостя"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Гость"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Вариант по умолчанию"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Отключено"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Включено"</string>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index a883cc6..dc9b702 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"සීමිත පැතිකඩක් නිර්මාණය කිරීමට කලින්. ඔබගේ යෙදුම් සහ පෞද්ගලික දත්ත ආරක්ෂා කිරීමට තිර අගුලක් සැකසිය යුතුයි."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"අගුල සකසන්න"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> වෙත මාරු වන්න"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"අමුත්තා එක් කරන්න"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"අමුත්තා ඉවත් කරන්න"</string>
<string name="guest_nickname" msgid="6332276931583337261">"අමුත්තා"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"උපාංගයේ පෙරනිමිය"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"අබල කළා"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"සබලයි"</string>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 05c6379..203f253 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -547,9 +547,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Pred vytvorením obmedzeného profilu je nutné najprv nastaviť zámku obrazovky na ochranu aplikácií a osobných údajov."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Nastaviť uzamknutie"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Prepnúť na používateľa <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Pridať hosťa"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Odobrať hosťa"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Hosť"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Predvol. nastavenie zariadenia"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Vypnuté"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Zapnuté"</string>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index fd216e8..3bfda06 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -547,9 +547,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Preden lahko ustvarite profil z omejitvami, morate nastaviti zaklepanje zaslona, da zaščitite aplikacije in osebne podatke."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Nastavi zaklepanje"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Preklop na račun <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Dodajanje gosta"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Odstranitev gosta"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Gost"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Privzeta nastavitev naprave"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Onemogočeno"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Omogočeno"</string>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 002c7fc..859cc70 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Para se të mund të krijosh një profil të kufizuar, duhet të konfigurosh një kyçje të ekranit për të mbrojtur aplikacionet dhe të dhënat e tua personale."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Cakto kyçjen"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Kalo te <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Shto të ftuar"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Hiq të ftuarin"</string>
<string name="guest_nickname" msgid="6332276931583337261">"I ftuar"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Parazgjedhja e pajisjes"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Joaktiv"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Aktiv"</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 25a1beb7..6c02c3c 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -546,9 +546,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Да бисте могли да направите ограничени профил, треба да подесите закључавање екрана да бисте заштитили апликације и личне податке."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Подеси закључавање"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Пређи на корисника <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Додај госта"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Уклони госта"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Гост"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Подразумевано за уређај"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Онемогућено"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Омогућено"</string>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 352cb0a..dc21675 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Innan du skapar en begränsad profil måste du konfigurera ett skärmlås för att skydda dina appar och personliga data."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Konfigurera lås"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Byt till <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Lägg till gäst"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Ta bort gäst"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Gäst"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Enhetens standardinställning"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Inaktiverat"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Aktiverat"</string>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index c5d70ac..8f80e55 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Kabla uunde wasifu uliowekekwa vikwazo, utahitajika kuweka skrini iliyofungwa ili kulinda programu zako na data binafsi."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Weka ufunguo"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Badili utumie <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Weka mgeni"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Ondoa mgeni"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Mgeni"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Hali chaguomsingi ya kifaa"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Imezimwa"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Imewashwa"</string>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index 7837dd8..1069421 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"நீங்கள் வரையறுக்கப்பட்டச் சுயவிவரத்தை உருவாக்குவதற்கு முன்பு, உங்கள் ஆப்ஸ் மற்றும் தனிப்பட்ட தரவைப் பாதுகாக்கும் வகையில் நீங்கள் திரைப் பூட்டை அமைக்க வேண்டும்."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"பூட்டை அமை"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g>க்கு மாறு"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"கெஸ்ட்டைச் சேர்"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"கெஸ்ட்டை அகற்று"</string>
<string name="guest_nickname" msgid="6332276931583337261">"கெஸ்ட்"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"சாதனத்தின் இயல்புநிலை"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"முடக்கப்பட்டது"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"இயக்கப்பட்டது"</string>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index e252eca..3ad2375 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"మీరు పరిమితం చేయబడిన ప్రొఫైల్ను సృష్టించడానికి ముందు, మీ అనువర్తనాలు మరియు వ్యక్తిగత డేటాను రక్షించడానికి స్క్రీన్ లాక్ను సెటప్ చేయాల్సి ఉంటుంది."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"లాక్ను సెట్ చేయి"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g>కు మార్చు"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"అతిథిని జోడించండి"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"అతిథిని తీసివేయండి"</string>
<string name="guest_nickname" msgid="6332276931583337261">"అతిథి"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"పరికర ఆటోమేటిక్ సెట్టింగ్"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"డిజేబుల్ చేయబడింది"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"ఎనేబుల్ చేయబడింది"</string>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 7468d04..cc0ac74 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"ก่อนที่คุณจะสามารถสร้างโปรไฟล์ที่ถูกจำกัดได้ คุณจะต้องตั้งค่าล็อกหน้าจอเพื่อปกป้องแอปและข้อมูลส่วนตัวของคุณ"</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"ตั้งค่าล็อก"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"เปลี่ยนเป็น <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"เพิ่มผู้เข้าร่วม"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"นำผู้เข้าร่วมออก"</string>
<string name="guest_nickname" msgid="6332276931583337261">"ผู้ใช้ชั่วคราว"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"ค่าเริ่มต้นของอุปกรณ์"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"ปิดใช้"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"เปิดใช้"</string>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 5d4e975..77ab7cf 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Bago ka makakalikha ng pinaghihigpitang profile, kakailanganin mong mag-set up ng screen lock upang protektahan ang iyong apps at personal na data."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Itakda ang lock"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Lumipat sa <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Magdagdag ng bisita"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Alisin ang bisita"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Bisita"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Default ng device"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Naka-disable"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Na-enable"</string>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index f01f3fa..9d980c4 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Kısıtlanmış bir profil oluşturabilmeniz için uygulamalarınızı ve kişisel verilerinizi korumak üzere bir ekran kilidi oluşturmanız gerekir."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Kilidi ayarla"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> hesabına geç"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Misafir ekle"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Misafir oturumunu kaldır"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Misafir"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Cihaz varsayılanı"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Devre dışı"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Etkin"</string>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index 9ca2f06..9a7b89f 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -547,9 +547,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Перш ніж створювати обмежений профіль, потрібно налаштувати блокування екрана, щоб захистити свої програми та особисті дані."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Налаштувати блокування"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Перейти до користувача <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Додати гостя"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Видалити гостя"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Гість"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"За умовчанням для пристрою"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Вимкнено"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Увімкнено"</string>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index 8953f50..1cc0859 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"ایک محدود پروفائل بنانے سے پہلے، آپ کو اپنی ایپس اور ذاتی ڈیٹا کو محفوظ کرنے کیلئے ایک اسکرین لاک سیٹ اپ کرنا ہوگا۔"</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"لاک سیٹ کریں"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> پر سوئچ کریں"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"مہمان کو شامل کریں"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"مہمان کو ہٹائیں"</string>
<string name="guest_nickname" msgid="6332276931583337261">"مہمان"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"آلہ ڈیفالٹ"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"غیر فعال"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"فعال"</string>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index f25b3ac..3df33b6 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -545,9 +545,14 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Cheklangan profil yaratish uchun, shaxsiy ilovlar va ma‘lumotlarni himoyalash maqsadida avval ekran qulfini yaratish lozim."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Qulf o‘rnatish"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Bunga almashish: <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Yangi foydalanuvchi yaratilmoqda…"</string>
+ <string name="user_nickname" msgid="262624187455825083">"Nik"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Mehmon kiritish"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Mehmon rejimini olib tashlash"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Mehmon"</string>
+ <string name="user_image_take_photo" msgid="467512954561638530">"Suratga olish"</string>
+ <string name="user_image_choose_photo" msgid="1363820919146782908">"Rasm tanlash"</string>
+ <string name="user_image_photo_selector" msgid="433658323306627093">"Surat tanlash"</string>
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Qurilma standarti"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Yoqilmagan"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Yoniq"</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index b5798f3..2ed6ca8 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Trước khi bạn có thể tạo tiểu sử bị hạn chế, bạn sẽ cần thiết lập một màn hình khóa để bảo vệ các ứng dụng và dữ liệu cá nhân của bạn."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Thiết lập khóa"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Chuyển sang <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Thêm khách"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Xóa phiên khách"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Khách"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Theo giá trị mặc định của thiết bị"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Đã tắt"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Đã bật"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index c4dcfff..024ea79 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"您需要先设置锁定屏幕来保护您的应用和个人数据,然后才可以创建受限个人资料。"</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"设置屏幕锁定方式"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"切换到<xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"添加访客"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"移除访客"</string>
<string name="guest_nickname" msgid="6332276931583337261">"访客"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"设备默认设置"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"已停用"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"已启用"</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index e04651c..75f050f 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"建立限制存取的個人檔案前,您必須先設定上鎖畫面來保護您的應用程式和個人資料。"</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"設定上鎖畫面"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"切換至<xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"新增訪客"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"移除訪客"</string>
<string name="guest_nickname" msgid="6332276931583337261">"訪客"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"裝置預設設定"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"已停用"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"已啟用"</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index a1ae6b6..9866b47 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"如要建立設有限制的個人資料,你必須先設定螢幕鎖定來保護你的應用程式和個人資料。"</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"設定鎖定"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"切換至<xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"新增訪客"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"移除訪客"</string>
<string name="guest_nickname" msgid="6332276931583337261">"訪客"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"裝置預設設定"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"已停用"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"已啟用"</string>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 2dafad8..b1825c4 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -545,9 +545,19 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Ngaphambi kokuthi ungadala iphrofayela ekhawulelwe, kuzomele usethe ukukhiya isikrini ukuze uvikele izinhlelo zakho zokusebenza nedatha yakho yomuntu siqu."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Setha ukukhiya"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Shintshela ku-<xliff:g id="USER_NAME">%s</xliff:g>"</string>
+ <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) -->
+ <skip />
+ <!-- no translation found for user_nickname (262624187455825083) -->
+ <skip />
<string name="guest_new_guest" msgid="3482026122932643557">"Engeza isivakashi"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Susa isihambeli"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Isihambeli"</string>
+ <!-- no translation found for user_image_take_photo (467512954561638530) -->
+ <skip />
+ <!-- no translation found for user_image_choose_photo (1363820919146782908) -->
+ <skip />
+ <!-- no translation found for user_image_photo_selector (433658323306627093) -->
+ <skip />
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Idivayisi ezenzakalelayo"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Ikhutshaziwe"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Inikwe amandla"</string>
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index a9843dc..69be144 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -440,6 +440,7 @@
Settings.Global.SHOW_NEW_APP_INSTALLED_NOTIFICATION_ENABLED,
Settings.Global.SHOW_NOTIFICATION_CHANNEL_WARNINGS,
Settings.Global.SHOW_PEOPLE_SPACE,
+ Settings.Global.SHOW_NEW_LOCKSCREEN,
Settings.Global.SHOW_RESTART_IN_CRASH_DIALOG,
Settings.Global.SHOW_TEMPERATURE_WARNING,
Settings.Global.SHOW_USB_TEMPERATURE_ALARM,
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index a927997..bba29db 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -329,6 +329,12 @@
<!-- Permission needed for CTS test - TimeManagerTest -->
<uses-permission android:name="android.permission.MANAGE_TIME_AND_ZONE_DETECTION" />
+ <!-- Permission required for CTS test - android.server.biometrics -->
+ <uses-permission android:name="android.permission.USE_BIOMETRIC" />
+
+ <!-- Permission required for CTS test - android.server.biometrics -->
+ <uses-permission android:name="android.permission.TEST_BIOMETRIC" />
+
<application android:label="@string/app_label"
android:theme="@android:style/Theme.DeviceDefault.DayNight"
android:defaultToDeviceProtectedStorage="true"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 7d3390d..31faedf 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Instellings"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Vergrotingvenster"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Vergrotingvensterkontroles"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Zoem in"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Zoem uit"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Skuif op"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Skuif af"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Beweeg links"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Beweeg regs"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Toestelkontroles"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Voeg kontroles vir jou gekoppelde toestelle by"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (ontkoppel)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Kon nie koppel nie. Probeer weer."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Bind nuwe toestel saam"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Bounommer"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Bounommer is na knipbord gekopieer."</string>
</resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index a91182e..41f6bed 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"ቅንብሮች"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"የማጉያ መስኮት"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"የማጉያ መስኮት መቆጣጠሪያዎች"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"አጉላ"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"አሳንስ"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"ወደ ላይ ውሰድ"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"ወደ ታች ውሰድ"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"ወደ ግራ ውሰድ"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"ወደ ቀኝ ውሰድ"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"የመሣሪያ መቆጣጠሪያዎች"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"ለእርስዎ የተገናኙ መሣሪያዎች መቆጣጠሪያዎችን ያክሉ"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (ግንኙነት ተቋርጧል)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"ማገናኘት አልተቻለም። እንደገና ይሞክሩ።"</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"አዲስ መሣሪያ ያጣምሩ"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"የግንብ ቁጥር"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"የገንባ ቁጥር ወደ ቅንጥብ ሰሌዳ ተቀድቷል።"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 74a9b64..d1f98f0 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -1032,17 +1032,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"الإعدادات"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"نافذة التكبير"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"عناصر التحكم في نافذة التكبير"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"تكبير"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"تصغير"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"نقل للأعلى"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"نقل للأسفل"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"نقل لليسار"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"نقل لليمين"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"أدوات التحكم بالأجهزة"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"إضافة عناصر تحكّم لأجهزتك المتصلة"</string>
@@ -1111,8 +1113,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (غير متّصل)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"تعذّر الاتصال. يُرجى إعادة المحاولة."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"إقران جهاز جديد"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"رقم الإصدار"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"تم نسخ رقم الإصدار إلى الحافظة."</string>
</resources>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 297d774..52b6c5a 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"ছেটিংসমূহ"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"বিবৰ্ধন ৱিণ্ড’"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"বিবৰ্ধন ৱিণ্ড’ৰ নিয়ন্ত্ৰণসমূহ"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"জুম ইন কৰক"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"জুম আউট কৰক"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"ওপৰলৈ নিয়ক"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"তললৈ নিয়ক"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"বাওঁফাললৈ নিয়ক"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"সোঁফাললৈ নিয়ক"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"ডিভাইচৰ নিয়ন্ত্ৰণসমূহ"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"আপোনাৰ সংযোজিত ডিভাইচসমূহৰ বাবে নিয়ন্ত্ৰণসমূহ যোগ কৰক"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (সংযোগ বিচ্ছিন্ন হৈছে)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"সংযোগ কৰিব পৰা নগ’ল। পুনৰ চেষ্টা কৰক।"</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"নতুন ডিভাইচ পেয়াৰ কৰক"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"বিল্ডৰ নম্বৰ"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"ক্লিপব’ৰ্ডলৈ বিল্ডৰ নম্বৰ প্ৰতিলিপি কৰা হ’ল।"</string>
</resources>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index debad02..b446718 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -797,7 +797,7 @@
<string name="keyboard_key_page_up" msgid="173914303254199845">"Yuxarı Səhifə"</string>
<string name="keyboard_key_page_down" msgid="9035902490071829731">"Aşağı Səhifə"</string>
<string name="keyboard_key_forward_del" msgid="5325501825762733459">"Silin"</string>
- <string name="keyboard_key_move_home" msgid="3496502501803911971">"Əsas səhifə"</string>
+ <string name="keyboard_key_move_home" msgid="3496502501803911971">"Home"</string>
<string name="keyboard_key_move_end" msgid="99190401463834854">"Son"</string>
<string name="keyboard_key_insert" msgid="4621692715704410493">"Daxil edin"</string>
<string name="keyboard_key_num_lock" msgid="7209960042043090548">"Nömrələr"</string>
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Ayarlar"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Böyütmə Pəncərəsi"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Böyütmə Pəncərəsi Kontrolları"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Yaxınlaşdırın"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Uzaqlaşdırın"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Yuxarı köçürün"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Aşağı köçürün"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Sola köçürün"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Sağa köçürün"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Cihaz idarəetmələri"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Qoşulmuş cihazlarınız üçün nizamlayıcılar əlavə edin"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (bağlantı kəsilib)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Qoşulmaq alınmadı. Yenə cəhd edin."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Yeni cihazı qoşalaşdırın"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Versiya nömrəsi"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Versiya nömrəsi mübadilə buferinə kopyalandı."</string>
</resources>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index be31c2d..3cc10d8 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -1017,17 +1017,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Podešavanja"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Prozor za uvećanje"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Kontrole prozora za uvećanje"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Uvećajte"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Umanjite"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Pomerite nagore"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Pomerite nadole"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Pomerite nalevo"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Pomerite nadesno"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Kontrole uređaja"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Dodajte kontrole za povezane uređaje"</string>
@@ -1093,8 +1095,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (veza je prekinuta)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Povezivanje nije uspelo. Probajte ponovo."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Upari novi uređaj"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Broj verzije"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Broj verzije je kopiran u privremenu memoriju."</string>
</resources>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index e3831a8..07e7f8a 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -1022,17 +1022,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Налады"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Акно павелічэння"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Налады акна павелічэння"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Павялічыць маштаб"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Паменшыць маштаб"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Перамясціць уверх"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Перамясціць ніжэй"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Перамясціць улева"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Перамясціць управа"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Элементы кіравання прыладай"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Дадайце элементы кіравання для падключаных прылад"</string>
@@ -1099,8 +1101,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (адключана)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Не ўдалося падключыцца. Паўтарыце спробу."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Спалучыць з новай прыладай"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Нумар зборкі"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Нумар зборкі скапіраваны ў буфер абмену."</string>
</resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index d959178..f33c5cf 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Настройки"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Прозорец за ниво на мащаба"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Контроли за прозореца за ниво на мащаба"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Увеличаване на мащаба"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Намаляване на мащаба"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Преместване нагоре"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Преместване надолу"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Преместване наляво"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Преместване надясно"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Контроли за устройството"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Добавяне на контроли за свързаните ви устройства"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (връзката е прекратена)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Неуспешно свързване. Опитайте отново."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Сдвояване на ново устройство"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Номер на компилацията"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Номерът на компилацията е копиран в буферната памет."</string>
</resources>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index fffa555..0b5d65e 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"সেটিংস"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"উইন্ডো বড় করে দেখা"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"উইন্ডো কন্ট্রোল বড় করে দেখা"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"বড় করুন"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"ছোট করুন"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"উপরে তুলুন"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"নিচে নামান"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"বাঁদিকে সরান"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"ডানদিকে সরান"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"ডিভাইস কন্ট্রোল"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"আপনার কানেক্ট করা ডিভাইসের জন্য কন্ট্রোল যোগ করুন"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (কানেক্ট করা নেই)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"কানেক্ট করা যায়নি। আবার চেষ্টা করুন।"</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"নতুন ডিভাইস পেয়ার করুন"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"বিল্ড নম্বর"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"বিল্ড নম্বর ক্লিপবোর্ডে কপি করা হয়েছে।"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index f5410cf..ac68620 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -726,7 +726,7 @@
<string name="bubble_overflow_empty_title" msgid="3120029421991510842">"Nema nedavnih oblačića"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2030874469510497397">"Nedavni i odbačeni oblačići će se pojaviti ovdje"</string>
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Ta obavještenja se ne mogu izmijeniti."</string>
- <string name="notification_multichannel_desc" msgid="7414593090056236179">"Ovdje nije moguće konfigurirati ovu grupu obavještenja"</string>
+ <string name="notification_multichannel_desc" msgid="7414593090056236179">"Ovu grupu obavještenja nije moguće konfigurirati ovdje"</string>
<string name="notification_delegate_header" msgid="1264510071031479920">"Obavještenje preko proksi servera"</string>
<string name="notification_channel_dialog_title" msgid="6856514143093200019">"Sva obavještenja aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="see_more_title" msgid="7409317011708185729">"Prikaži više"</string>
@@ -1017,17 +1017,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Postavke"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Prozor za uvećavanje"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Kontrole prozora za uvećavanje"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Uvećavanje"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Umanjivanje"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Pomjeranje prema gore"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Pomjeranje prema dolje"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Pomjeranje lijevo"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Pomjeranje desno"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Kontrole uređaja"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Dodajte kontrole za povezane uređaje"</string>
@@ -1093,8 +1095,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (veza je prekinuta)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Povezivanje nije uspjelo. Pokušajte ponovo."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Uparite novi uređaj"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Broj verzije"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Broj verzije je kopiran u međumemoriju."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 28bf3bb..5e64aee 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Configuració"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Finestra d\'ampliació"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Finestra de controls d\'ampliació"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Amplia"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Redueix"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Mou cap amunt"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Mou cap avall"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Mou cap a l\'esquerra"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Mou cap a la dreta"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Controls de dispositius"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Afegeix controls per als teus dispositius connectats"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (desconnectat)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"No s\'ha pogut connectar. Torna-ho a provar."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Vincula un dispositiu nou"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Número de compilació"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"El número de compilació s\'ha copiat al porta-retalls."</string>
</resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index c66f200..5ca5df6 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -1022,17 +1022,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Nastavení"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Zvětšovací okno"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Ovládací prvky zvětšovacího okna"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Přiblížit"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Oddálit"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Přesunout nahoru"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Přesunout dolů"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Přesunout doleva"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Přesunout doprava"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Ovládání zařízení"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Přidejte ovládací prvky pro připojená zařízení"</string>
@@ -1099,8 +1101,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (odpojeno)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Spojení se nezdařilo. Zkuste to znovu."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Spárovat nové zařízení"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Číslo sestavení"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Číslo sestavení bylo zkopírováno do schránky."</string>
</resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 5b0566d..419740e 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Indstillinger"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Vindue med forstørrelse"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Vindue med forstørrelsesstyring"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Zoom ind"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Zoom ud"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Flyt op"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Flyt ned"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Flyt til venstre"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Flyt til højre"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Enhedsstyring"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Tilføj styring af dine tilsluttede enheder"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (ingen forbindelse)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Der kunne ikke oprettes forbindelse. Prøv igen."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Par ny enhed"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Buildnummer"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Buildnummeret blev kopieret til udklipsholderen."</string>
</resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 0ab1f0e..4b1be3b 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Einstellungen"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Vergrößerungsfenster"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Einstellungen für Vergrößerungsfenster"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Heranzoomen"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Herauszoomen"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Nach oben bewegen"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Nach unten bewegen"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Nach links bewegen"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Nach rechts bewegen"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Gerätesteuerung"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Steuerelemente für verbundene Geräte hinzufügen"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (nicht verbunden)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Verbindung nicht möglich. Versuch es noch einmal."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Neues Gerät koppeln"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Build-Nummer"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Build-Nummer in Zwischenablage kopiert."</string>
</resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 6d86e91..fc4e78b 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -1012,18 +1012,16 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Ρυθμίσεις"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Παράθυρο μεγέθυνσης"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Στοιχεία ελέγχου παραθύρου μεγέθυνσης"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
- <skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
- <skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
- <skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
- <skip />
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Μεγέθυνση"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Σμίκρυνση"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Μετακίνηση επάνω"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Μετακίνηση κάτω"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Μετακίνηση αριστερά"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Μετακίνηση δεξιά"</string>
+ <string name="magnification_mode_switch_description" msgid="2698364322069934733">"Εναλλαγή μεγιστοποίησης"</string>
+ <string name="magnification_mode_switch_state_full_screen" msgid="2882507327576770574">"Μεγέθυνση ολόκληρης της οθόνης"</string>
+ <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Μεγέθυνση μέρους της οθόνης"</string>
+ <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Εναλλαγή"</string>
<string name="quick_controls_title" msgid="6839108006171302273">"Στοιχεία ελέγχου συσκευής"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Προσθήκη στοιχείων ελέγχου για τις συνδεδεμένες συσκευές σας."</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Ρύθμιση στοιχείων ελέγχου συσκευής"</string>
@@ -1087,8 +1085,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (αποσυνδέθηκε)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Δεν ήταν δυνατή η σύνδεση. Δοκιμάστε ξανά."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Σύζευξη νέας συσκευής"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Αριθμός έκδοσης"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Ο αριθμός έκδοσης αντιγράφηκε στο πρόχειρο."</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index cb03d40..709a506 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -1018,6 +1018,10 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Move down"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Move left"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Move right"</string>
+ <string name="magnification_mode_switch_description" msgid="2698364322069934733">"Magnification switch"</string>
+ <string name="magnification_mode_switch_state_full_screen" msgid="2882507327576770574">"Magnify entire screen"</string>
+ <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Magnify part of screen"</string>
+ <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Switch"</string>
<string name="quick_controls_title" msgid="6839108006171302273">"Device controls"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Add controls for your connected devices"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Set up device controls"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index 8e5849e..79a2844 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -1018,6 +1018,10 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Move down"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Move left"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Move right"</string>
+ <string name="magnification_mode_switch_description" msgid="2698364322069934733">"Magnification switch"</string>
+ <string name="magnification_mode_switch_state_full_screen" msgid="2882507327576770574">"Magnify entire screen"</string>
+ <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Magnify part of screen"</string>
+ <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Switch"</string>
<string name="quick_controls_title" msgid="6839108006171302273">"Device controls"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Add controls for your connected devices"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Set up device controls"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index cb03d40..709a506 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -1018,6 +1018,10 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Move down"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Move left"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Move right"</string>
+ <string name="magnification_mode_switch_description" msgid="2698364322069934733">"Magnification switch"</string>
+ <string name="magnification_mode_switch_state_full_screen" msgid="2882507327576770574">"Magnify entire screen"</string>
+ <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Magnify part of screen"</string>
+ <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Switch"</string>
<string name="quick_controls_title" msgid="6839108006171302273">"Device controls"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Add controls for your connected devices"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Set up device controls"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index cb03d40..709a506 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -1018,6 +1018,10 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Move down"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Move left"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Move right"</string>
+ <string name="magnification_mode_switch_description" msgid="2698364322069934733">"Magnification switch"</string>
+ <string name="magnification_mode_switch_state_full_screen" msgid="2882507327576770574">"Magnify entire screen"</string>
+ <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Magnify part of screen"</string>
+ <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Switch"</string>
<string name="quick_controls_title" msgid="6839108006171302273">"Device controls"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Add controls for your connected devices"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Set up device controls"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index e107ed5..ab6699b 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -1018,6 +1018,10 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Move down"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Move left"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Move right"</string>
+ <string name="magnification_mode_switch_description" msgid="2698364322069934733">"Magnification switch"</string>
+ <string name="magnification_mode_switch_state_full_screen" msgid="2882507327576770574">"Magnify entire screen"</string>
+ <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Magnify part of screen"</string>
+ <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Switch"</string>
<string name="quick_controls_title" msgid="6839108006171302273">"Device controls"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Add controls for your connected devices"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Set up device controls"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index be37623..a1e21a1 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -1012,18 +1012,16 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Configuración"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Ventana de ampliación"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Controles de ampliación de la ventana"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
- <skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
- <skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
- <skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
- <skip />
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Acercar"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Alejar"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Mover hacia arriba"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Mover hacia abajo"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Mover hacia la izquierda"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Mover hacia la derecha"</string>
+ <string name="magnification_mode_switch_description" msgid="2698364322069934733">"Botón de ampliación"</string>
+ <string name="magnification_mode_switch_state_full_screen" msgid="2882507327576770574">"Ampliar toda la pantalla"</string>
+ <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Ampliar parte de la pantalla"</string>
+ <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Botón"</string>
<string name="quick_controls_title" msgid="6839108006171302273">"Controles de dispositivos"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Agrega controles para los dispositivos conectados"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Configurar controles de dispositivos"</string>
@@ -1087,8 +1085,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (desconectado)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"No se pudo establecer la conexión. Vuelve a intentarlo."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Vincular dispositivo nuevo"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Número de compilación"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Se copió el número de compilación en el portapapeles."</string>
</resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 08b17cc..51c6d0d 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Ajustes"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Ventana de ampliación"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Ventana de controles de ampliación"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Ampliar"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Reducir"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Mover hacia arriba"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Mover hacia abajo"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Mover hacia la izquierda"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Mover hacia la derecha"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Control de dispositivos"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Añade controles para tus dispositivos conectados"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (desconectado)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"No se ha podido conectar. Inténtalo de nuevo."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Vincular nuevo dispositivo"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Número de compilación"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Número de compilación copiado en el portapapeles."</string>
</resources>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index b33ad01..6d616b8 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Seaded"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Suurendamisaken"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Suurendamisakna juhtelemendid"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Suumi sisse"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Suumi välja"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Teisalda üles"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Teisalda alla"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Teisalda vasakule"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Teisalda paremale"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Seadmete juhikud"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Lisage juhtelemendid ühendatud seadmete jaoks"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (pole ühendatud)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Ühenduse loomine ebaõnnestus. Proovige uuesti."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Uue seadme sidumine"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Järgunumber"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Järgunumber kopeeriti lõikelauale."</string>
</resources>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 3f1a53c..05e52f4 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Ezarpenak"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Lupa-leihoa"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Lupa-leihoaren aukerak"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Handitu"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Txikitu"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Eraman gora"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Eraman behera"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Eraman ezkerrera"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Eraman eskuinera"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Gailuak kontrolatzeko widgetak"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Gehitu konektatutako gailuak kontrolatzeko widgetak"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (deskonektatuta)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Ezin izan da konektatu. Saiatu berriro."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Parekatu beste gailu batekin"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Konpilazio-zenbakia"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Kopiatu da konpilazio-zenbakia arbelean."</string>
</resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index e5606a2..1c16b33 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -431,7 +431,7 @@
<string name="quick_settings_screen_record_start" msgid="1574725369331638985">"شروع"</string>
<string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"توقف"</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"دستگاه"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"برای تغییر برنامهها، تند به بالا بکشید"</string>
+ <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"برای تغییر برنامهها، تند بهبالا بکشید"</string>
<string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"برای جابهجایی سریع میان برنامهها، به چپ بکشید"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"تغییر وضعیت نمای کلی"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"شارژ کامل شد"</string>
@@ -450,8 +450,8 @@
<string name="keyguard_more_overflow_text" msgid="5819512373606638727">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="7248696377626341060">"اعلانهای کمتر فوری در زیر"</string>
<string name="notification_tap_again" msgid="4477318164947497249">"دوباره ضربه بزنید تا باز شود"</string>
- <string name="keyguard_unlock" msgid="8031975796351361601">"برای باز کردن، انگشتتان را تند به بالا بکشید"</string>
- <string name="keyguard_retry" msgid="886802522584053523">"برای امتحان مجدد، انگشتتان را تند به بالا بکشید"</string>
+ <string name="keyguard_unlock" msgid="8031975796351361601">"برای باز کردن، انگشتتان را تند بهبالا بکشید"</string>
+ <string name="keyguard_retry" msgid="886802522584053523">"برای امتحان مجدد، انگشتتان را تند بهبالا بکشید"</string>
<string name="do_disclosure_generic" msgid="4896482821974707167">"این دستگاه به سازمان شما تعلق دارد"</string>
<string name="do_disclosure_with_name" msgid="2091641464065004091">"این دستگاه به <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> تعلق دارد"</string>
<string name="phone_hint" msgid="6682125338461375925">"انگشتتان را از نماد تلفن تند بکشید"</string>
@@ -740,7 +740,7 @@
<string name="feedback_promoted" msgid="8075757485407091976">"سیستمْ این اعلان را ارتقا داده است."</string>
<string name="feedback_demoted" msgid="5848066008939031913">"سیستمْ این اعلان را تنزل داده است."</string>
<string name="feedback_prompt" msgid="2278631214125128281">"این مورد درست بود؟"</string>
- <string name="feedback_response" msgid="4671729244976641339">"از بازخورد شما سپاسگذاریم!"</string>
+ <string name="feedback_response" msgid="4671729244976641339">"از بازخوردتان سپاسگزاریم!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"تأیید"</string>
<string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"کنترلهای اعلان برای <xliff:g id="APP_NAME">%1$s</xliff:g> باز شد"</string>
<string name="notification_channel_controls_closed_accessibility" msgid="1561909368876911701">"کنترلهای اعلان برای <xliff:g id="APP_NAME">%1$s</xliff:g> بسته شد"</string>
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"تنظیمات"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"پنجره بزرگنمایی"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"کنترلهای پنجره بزرگنمایی"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"بزرگ کردن"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"کوچک کردن"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"انتقال به بالا"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"انتقال به پایین"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"انتقال به راست"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"انتقال به چپ"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"کنترلهای دستگاه"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"افزودن کنترلها برای دستگاههای متصل"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (اتصال قطع شد)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"متصل نشد. دوباره امتحان کنید."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"مرتبط کردن دستگاه جدید"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"شماره ساخت"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"شماره ساخت در بریدهدان کپی شد."</string>
</resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index e00b50e..1e900fb 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Asetukset"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Suurennusikkuna"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Suurennusikkunan ohjaimet"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Lähennä"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Loitonna"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Siirrä ylös"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Siirrä alas"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Siirrä vasemmalle"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Siirrä oikealle"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Laitteiden hallinta"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Lisää ohjaimia yhdistettyjä laitteita varten"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (yhteys katkaistu)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Ei yhteyttä. Yritä uudelleen."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Muodosta uusi laitepari"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Koontiversion numero"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Koontiversion numero kopioitu leikepöydälle"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 03e205d..f390693 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Paramètres"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Fenêtre d\'agrandissement"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Commandes pour la fenêtre d\'agrandissement"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Effectuer un zoom avant"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Effectuer un zoom arrière"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Déplacer vers le haut"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Déplacer vers le bas"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Déplacer vers la gauche"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Déplacer vers la droite"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Commandes des appareils"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Ajoutez des commandes pour vos appareils connectés"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (déconnecté)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Impossible de se connecter. Réessayez."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Associer un autre appareil"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Numéro de version"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Le numéro de version a été copié dans le presse-papiers."</string>
</resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 82df63a..df542bc 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Paramètres"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Fenêtre d\'agrandissement"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Fenêtre des commandes d\'agrandissement"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Faire un zoom avant"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Faire un zoom arrière"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Déplacer vers le haut"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Déplacer vers le bas"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Déplacer vers la gauche"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Déplacer vers la droite"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Commandes des appareils"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Ajouter des commandes pour vos appareils connectés"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (déconnecté)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Impossible de se connecter. Réessayez."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Associer un nouvel appareil"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Numéro de build"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Numéro de build copié dans le presse-papiers."</string>
</resources>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 9be451d..fedbe2c 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Configuración"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Ventá de superposición"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Controis de ampliación da ventá"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Achegar"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Afastar"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Mover cara arriba"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Mover cara abaixo"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Mover cara á esquerda"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Mover cara á dereita"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Control de dispositivos"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Engade controis para os dispositivos conectados"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (dispositivo desconectado)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Non se puido establecer a conexión. Téntao de novo."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Vincular dispositivo novo"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Número de compilación"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Copiouse o número de compilación no portapapeis."</string>
</resources>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 864d05f..d9c5b72 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"સેટિંગ"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"વિસ્તૃતીકરણ વિંડો"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"વિસ્તૃતીકરણ વિંડોના નિયંત્રણો"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"મોટું કરો"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"નાનું કરો"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"ઉપર ખસેડો"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"નીચે ખસેડો"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"ડાબી બાજુ ખસેડો"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"જમણી બાજુ ખસેડો"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"ડિવાઇસનાં નિયંત્રણો"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"તમારા કનેક્ટ કરેલા ડિવાઇસ માટે નિયંત્રણો ઉમેરો"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (ડિસ્કનેક્ટ થયેલું)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"કનેક્ટ કરી શકાયું નહીં. ફરી પ્રયાસ કરો."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"નવા ડિવાઇસ સાથે જોડાણ કરો"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"બિલ્ડ નંબર"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"બિલ્ડ નંબર ક્લિપબૉર્ડ પર કૉપિ કર્યો."</string>
</resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index e11055c..08149fb 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -1014,17 +1014,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"सेटिंग"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"स्क्रीन को बड़ा करके दिखाने वाली विंडो"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"स्क्रीन को बड़ा करके दिखाने वाली विंडो के नियंत्रण"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"ज़ूम इन करें"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"ज़ूम आउट करें"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"ऊपर ले जाएं"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"नीचे ले जाएं"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"बाईं ओर ले जाएं"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"दाईं ओर ले जाएं"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"डिवाइस कंट्रोल"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"कनेक्ट किए गए डिवाइस के लिए कंट्रोल जोड़ें"</string>
@@ -1089,8 +1091,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (डिसकनेक्ट किया गया)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"कनेक्ट नहीं किया जा सका. फिर से कोशिश करें."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"नया डिवाइस जोड़ें"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"बिल्ड नंबर"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"बिल्ड नंबर को क्लिपबोर्ड पर कॉपी किया गया."</string>
</resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index d5033fa..b01f58e 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -1017,17 +1017,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Postavke"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Prozor za povećavanje"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Kontrole prozora za povećavanje"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Povećaj"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Smanji"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Premjesti gore"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Premjesti dolje"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Premjesti ulijevo"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Premjesti udesno"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Kontrole uređaja"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Dodavanje kontrola za povezane uređaje"</string>
@@ -1093,8 +1095,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (nije povezano)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Povezivanje nije bilo moguće. Pokušajte ponovo."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Upari novi uređaj"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Broj međuverzije"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Broj međuverzije kopiran je u međuspremnik."</string>
</resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 6d960e7..1fcabcf 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Beállítások"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Nagyítás ablaka"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Nagyítási vezérlők ablaka"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Nagyítás"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Kicsinyítés"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Mozgatás felfelé"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Mozgatás lefelé"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Mozgatás balra"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Mozgatás jobbra"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Eszközvezérlők"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Vezérlők hozzáadása a csatlakoztatott eszközökhöz"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (leválasztva)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Sikertelen csatlakozás. Próbálja újra."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Új eszköz párosítása"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Buildszám"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Buildszám a vágólapra másolva."</string>
</resources>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 9e746fa..63737d2 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Կարգավորումներ"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Խոշորացման պատուհան"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Խոշորացման պատուհանի կառավարման տարրեր"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Մեծացնել"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Փոքրացնել"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Տեղափոխել վերև"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Տեղափոխել ներքև"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Տեղափոխել ձախ"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Տեղափոխել աջ"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Սարքերի կառավարման տարրեր"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Ավելացրեք կառավարման տարրեր ձեր միացված սարքերի համար"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (անջատված է)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Չհաջողվեց միանալ։ Նորից փորձեք։"</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Նոր սարքի զուգակցում"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Կառուցման համարը"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Կառուցման համարը պատճենվեց սեղմատախտակին։"</string>
</resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 380e943..da9af02 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Setelan"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Jendela Pembesaran"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Kontrol Jendela Pembesaran"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Perbesar"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Perkecil"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Pindahkan ke atas"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Pindahkan ke bawah"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Pindahkan ke kiri"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Pindahkan ke kanan"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Kontrol perangkat"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Tambahkan kontrol untuk perangkat terhubung"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (terputus)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Tidak dapat terhubung. Coba lagi."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Sambungkan perangkat baru"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Nomor versi"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Nomor versi disalin ke papan klip."</string>
</resources>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index dd12ed6..64ad21f 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Stillingar"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Stækkunargluggi"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Stækkunarstillingar glugga"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Auka aðdrátt"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Minnka aðdrátt"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Færa upp"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Færa niður"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Færa til vinstri"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Færa til hægri"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Tækjastjórnun"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Bæta við stýringum fyrir tengd tæki"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (aftengt)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Tenging mistókst. Reyndu aftur."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Para nýtt tæki"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Útgáfunúmer smíðar"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Útgáfunúmer smíðar afritað á klippiborð."</string>
</resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 851228f..90f68d9 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Impostazioni"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Finestra ingrandimento"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Finestra controlli di ingrandimento"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Aumenta lo zoom"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Diminuisci lo zoom"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Sposta su"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Sposta giù"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Sposta a sinistra"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Sposta a destra"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Controllo dei dispositivi"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Aggiungi controlli per i dispositivi connessi"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (disconnesso)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Impossibile connettersi. Riprova."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Accoppia nuovo dispositivo"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Numero build"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Numero build copiato negli appunti."</string>
</resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index d4ad45e..14b19c3 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -941,7 +941,7 @@
<string name="notification_channel_general" msgid="4384774889645929705">"הודעות כלליות"</string>
<string name="notification_channel_storage" msgid="2720725707628094977">"אחסון"</string>
<string name="notification_channel_hints" msgid="7703783206000346876">"טיפים"</string>
- <string name="instant_apps" msgid="8337185853050247304">"אפליקציות אינסטנט"</string>
+ <string name="instant_apps" msgid="8337185853050247304">"אפליקציות ללא התקנה"</string>
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> פועלת"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"האפליקציה נפתחת בלי התקנה."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"האפליקציה נפתחת בלי התקנה. אפשר להקיש כדי לקבל מידע נוסף."</string>
@@ -1022,17 +1022,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"הגדרות"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"חלון הגדלה"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"בקרות של חלון ההגדלה"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"התקרבות"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"התרחקות"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"הזזה למעלה"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"הזזה למטה"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"הזזה שמאלה"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"הזזה ימינה"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"פקדי מכשירים"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"יש להוסיף פקדים למכשירים המחוברים"</string>
@@ -1099,8 +1101,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (מנותק)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"לא ניתן היה להתחבר. יש לנסות שוב."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"התאמה של מכשיר חדש"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"מספר Build"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"מספר ה-Build הועתק ללוח."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 7547853..98e6984 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"設定"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"拡大ウィンドウ"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"拡大ウィンドウ コントロール"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"拡大"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"縮小"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"上に移動"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"下に移動"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"左に移動"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"右に移動"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"デバイス コントロール"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"接続済みデバイスのコントロールを追加します"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>(未接続)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"接続できませんでした。もう一度お試しください。"</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"新しいデバイスとのペア設定"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"ビルド番号"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"ビルド番号をクリップボードにコピーしました。"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index 69b1d14..0086868 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -1012,18 +1012,16 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"პარამეტრები"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"გადიდების ფანჯარა"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"გადიდების კონტროლის ფანჯარა"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
- <skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
- <skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
- <skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
- <skip />
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"მასშტაბის გადიდება"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"მასშტაბის შემცირება"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"ზემოთ გადატანა"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"ქვემოთ გადატანა"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"მარცხნივ გადატანა"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"მარჯვნივ გადატანა"</string>
+ <string name="magnification_mode_switch_description" msgid="2698364322069934733">"გადიდების გადართვა"</string>
+ <string name="magnification_mode_switch_state_full_screen" msgid="2882507327576770574">"მთლიანი ეკრანის გადიდება"</string>
+ <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"ეკრანის ნაწილის გადიდება"</string>
+ <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"გადართვა"</string>
<string name="quick_controls_title" msgid="6839108006171302273">"მოწყობილ. მართვის საშუალებები"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"მართვის საშუალებების დამატება თქვენს დაკავშირებულ მოწყობილობებზე"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"მოწყობილობის მართვის საშუალებების დაყენება"</string>
@@ -1087,8 +1085,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (კავშირი გაწყვეტილია)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"დაკავშირება ვერ მოხერხდა. ცადეთ ხელახლა."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"ახალი მოწყობილობის დაწყვილება"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"ანაწყობის ნომერი"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"ანაწყობის ნომერი დაკოპირებულია გაცვლის ბუფერში."</string>
</resources>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index b86f32e..606350c 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Параметрлер"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Ұлғайту терезесі"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Ұлғайту терезесінің басқару элементтері"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Ұлғайту"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Кішірейту"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Жоғары қарай жылжыту"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Төмен қарай жылжыту"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Солға жылжыту"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Оңға жылжыту"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Құрылғыны басқару элементтері"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Жалғанған құрылғылар үшін басқару виджеттерін қосу"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (ажыратылған)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Қосылмады. Қайта қосылып көріңіз."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Жаңа құрылғыны жұптау"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Құрама нөмірі"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Құрама нөмірі буферге көшірілді."</string>
</resources>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index e895140..9ed01c5 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"ការកំណត់"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"វិនដូការពង្រីក"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"វិនដូគ្រប់គ្រងការពង្រីក"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"ពង្រីក"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"បង្រួម"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"ផ្លាស់ទីឡើងលើ"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"ផ្លាស់ទីចុះក្រោម"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"ផ្លាស់ទីទៅឆ្វេង"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"ផ្លាស់ទីទៅស្តាំ"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"ផ្ទាំងគ្រប់គ្រងឧបករណ៍"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"បញ្ចូលផ្ទាំងគ្រប់គ្រងសម្រាប់ឧបករណ៍ដែលអ្នកបានភ្ជាប់"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (បានផ្ដាច់)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"មិនអាចភ្ជាប់បានទេ។ សូមព្យាយាមម្ដងទៀត។"</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"ផ្គូផ្គងឧបករណ៍ថ្មី"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"លេខកំណែបង្កើត"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"បានចម្លងលេខកំណែបង្កើតទៅឃ្លីបបត។"</string>
</resources>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 2a9f649..116241c 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"ಸೆಟ್ಟಿಂಗ್ಗಳು"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"ವರ್ಧನೆಯ ವಿಂಡೋ"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"ವರ್ಧನೆಯ ವಿಂಡೋ ನಿಯಂತ್ರಣಗಳು"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"ಝೂಮ್ ಇನ್ ಮಾಡಿ"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"ಝೂಮ್ ಔಟ್ ಮಾಡಿ"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"ಮೇಲೆಕ್ಕೆ ಸರಿಸಿ"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"ಕೆಳಗೆ ಸರಿಸಿ"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"ಎಡಕ್ಕೆ ಸರಿಸಿ"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"ಬಲಕ್ಕೆ ಸರಿಸಿ"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"ಸಾಧನ ನಿಯಂತ್ರಣಗಳು"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"ನಿಮ್ಮ ಸಂಪರ್ಕಿತ ಸಾಧನಗಳಿಗೆ ನಿಯಂತ್ರಣಗಳನ್ನು ಸೇರಿಸಿ"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (ಸಂಪರ್ಕ ಕಡಿತಗೊಳಿಸಲಾಗಿದೆ)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"ಸಂಪರ್ಕಿಸಲು ಸಾಧ್ಯವಾಗುತ್ತಿಲ್ಲ. ಪುನಃ ಪ್ರಯತ್ನಿಸಿ."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"ಹೊಸ ಸಾಧನವನ್ನು ಜೋಡಿಸಿ"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"ಬಿಲ್ಡ್ ಸಂಖ್ಯೆ"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"ಬಿಲ್ಡ್ ಸಂಖ್ಯೆಯನ್ನು ಕ್ಲಿಪ್ಬೋರ್ಡ್ನಲ್ಲಿ ನಕಲಿಸಲಾಗಿದೆ."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 559205c..5bb0d13 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"설정"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"확대 창"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"확대 창 컨트롤"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"확대"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"축소"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"위로 이동"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"아래로 이동"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"왼쪽으로 이동"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"오른쪽으로 이동"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"기기 컨트롤"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"연결된 기기의 컨트롤을 추가하세요."</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>(연결 끊김)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"연결할 수 없습니다. 다시 시도하세요."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"새 기기와 페어링"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"빌드 번호"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"빌드 번호가 클립보드에 복사되었습니다."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index a688150..dd85504 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Жөндөөлөр"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Чоңойтуу терезеси"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Чоңойтуу терезесин башкаруу каражаттары"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Жакындатуу"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Алыстатуу"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Жогору жылдыруу"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Төмөн жылдыруу"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Солго жылдыруу"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Оңго жылдыруу"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Түзмөктү башкаруу элементтери"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Байланышкан түзмөктөрүңүздү башкаруу элементтерин кошосуз"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (ажыратылды)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Байланышпай койду. Кайталоо."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Жаңы түзмөктү жупташтыруу"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Курама номери"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Курама номери алмашуу буферине көчүрүлдү."</string>
</resources>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 1a6c338..3553704 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"ການຕັ້ງຄ່າ"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"ໜ້າຈໍການຂະຫຍາຍ"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"ການຄວບຄຸມໜ້າຈໍການຂະຫຍາຍ"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"ຊູມເຂົ້າ"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"ຊູມອອກ"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"ຍ້າຍຂຶ້ນ"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"ຍ້າຍລົງ"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"ຍ້າຍໄປຊ້າຍ"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"ຍ້າຍໄປຂວາ"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"ການຄວບຄຸມອຸປະກອນ"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"ເພີ່ມການຄວບຄຸມສຳລັບອຸປະກອນທີ່ເຊື່ອມຕໍ່ແລ້ວຂອງທ່ານ"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (ຕັດການເຊື່ອມຕໍ່ແລ້ວ)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"ບໍ່ສາມາດເຊື່ອມຕໍ່ໄດ້. ລອງໃໝ່."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"ຈັບຄູ່ອຸປະກອນໃໝ່"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"ໝາຍເລກສ້າງ"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"ສຳເນົາໝາຍເລກສ້າງໄປໃສ່ຄລິບບອດແລ້ວ."</string>
</resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 6fb84dd8..9a2a8f2 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -1028,6 +1028,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Perkelti žemyn"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Perkelti kairėn"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Perkelti dešinėn"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
+ <skip />
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
+ <skip />
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
+ <skip />
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Įrenginio valdikliai"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Pridėkite prijungtų įrenginių valdiklių"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Įrenginio valdiklių nustatymas"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 9864a61..94b66f3 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -1017,17 +1017,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Iestatījumi"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Palielināšanas logs"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Palielināšanas loga vadīklas"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Tuvināt"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Tālināt"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Pārvietot uz augšu"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Pārvietot uz leju"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Pārvietot pa kreisi"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Pārvietot pa labi"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Ierīču vadīklas"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Pievienojiet vadīklas pievienotajām ierīcēm"</string>
@@ -1093,8 +1095,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (savienojums pārtraukts)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Nevarēja izveidot savienojumu. Mēģiniet vēlreiz."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Savienošana pārī ar jaunu ierīci"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Versijas numurs"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Versijas numurs ir kopēts starpliktuvē."</string>
</resources>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 362cbdc..567afc0 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Поставки"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Прозорец за зголемување"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Контроли на прозорец за зголемување"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Зумирај"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Одзумирај"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Премести нагоре"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Премести надолу"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Премести налево"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Премести надесно"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Контроли за уредите"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Додајте контроли за поврзаните уреди"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (исклучен)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Не можеше да се поврзе. Обидете се повторно."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Спарете нов уред"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Број на верзија"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Бројот на верзијата е копиран во привремената меморија."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 95634b8..dc6fe4c 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"ക്രമീകരണം"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"മാഗ്നിഫിക്കേഷൻ വിൻഡോ"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"മാഗ്നിഫിക്കേഷൻ വിൻഡോ നിയന്ത്രണങ്ങൾ"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"സൂം ഇൻ ചെയ്യുക"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"സൂം ഔട്ട് ചെയ്യുക"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"മുകളിലേക്ക് നീക്കുക"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"താഴേക്ക് നീക്കുക"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"ഇടത്തേക്ക് നീക്കുക"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"വലത്തേക്ക് നീക്കുക"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"ഉപകരണ നിയന്ത്രണങ്ങൾ"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"കണക്റ്റ് ചെയ്ത ഉപകരണങ്ങൾക്ക് നിയന്ത്രണങ്ങൾ ചേർക്കുക"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (വിച്ഛേദിച്ചു)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"കണക്റ്റ് ചെയ്യാനായില്ല. വീണ്ടും ശ്രമിക്കുക."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"പുതിയ ഉപകരണവുമായി ജോടിയാക്കുക"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"ബിൽഡ് നമ്പർ"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"ക്ലിപ്പ്ബോർഡിലേക്ക് ബിൽഡ് നമ്പർ പകർത്തി."</string>
</resources>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index a2e1745..b12c4e0 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Тохиргоо"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Томруулалтын цонх"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Томруулалтын цонхны хяналт"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Томруулах"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Жижигрүүлэх"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Дээш зөөх"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Доош зөөх"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Зүүн тийш зөөх"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Баруун тийш зөөх"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Төхөөрөмжийн хяналт"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Холбогдсон төхөөрөмжүүд дээрээ хяналт нэмэх"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (салсан)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Холбогдож чадсангүй. Дахин оролдоно уу."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Шинэ төхөөрөмж хослуулах"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Хийгдсэн дугаар"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Хийгдсэн дугаарыг түр санах ойд хуулсан."</string>
</resources>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 7a62c17..40a51c7 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"सेटिंग्ज"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"मॅग्निफिकेशन विंडो"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"मॅग्निफिकेशन विंडो नियंत्रणे"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"झूम इन करा"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"झूम आउट करा"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"वर हलवा"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"खाली हलवा"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"डावीकडे हलवा"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"उजवीकडे हलवा"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"डिव्हाइस नियंत्रणे"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"तुमच्या कनेक्ट केलेल्या डिव्हाइससाठी नियंत्रणे जोडा"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (डिस्कनेक्ट केले)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"कनेक्ट करू शकलो नाही. पुन्हा प्रयत्न करा."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"नवीन डिव्हाइससोबत पेअर करा"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"बिल्ड नंबर"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"बिल्ड नंबर क्लिपबोर्डवर कॉपी केला."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 2b501bb..aa302a9 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Tetapan"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Tetingkap Pembesaran"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Kawalan Tetingkap Pembesaran"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Zum masuk"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Zum keluar"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Alih ke atas"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Alih ke bawah"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Alih ke kiri"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Alih ke kanan"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Kawalan peranti"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Tambah kawalan untuk peranti yang disambungkan"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (diputuskan sambungan)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Tidak boleh menyambung. Cuba lagi."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Gandingkan peranti baharu"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Nombor binaan"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Nombor binaan disalin ke papan keratan."</string>
</resources>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 1cbf17fe..a296b46 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"ဆက်တင်များ"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"ဝင်းဒိုး ချဲ့ခြင်း"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"ဝင်းဒိုး ထိန်းချုပ်မှုများ ချဲ့ခြင်း"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"ဇူးမ်ဆွဲရန်"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"ဇူးမ်ဖြုတ်ရန်"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"အပေါ်သို့ရွှေ့ရန်"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"အောက်သို့ရွှေ့ရန်"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"ဘယ်ဘက်သို့ရွှေ့ရန်"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"ညာဘက်သို့ရွှေ့ရန်"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"စက်ထိန်းစနစ်"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"ချိတ်ဆက်စက်များအတွက် ထိန်းချုပ်မှုများထည့်ပါ"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (ချိတ်ဆက်မထားပါ)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"ချိတ်ဆက်၍ မရပါ။ ထပ်စမ်းကြည့်ပါ။"</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"စက်အသစ် တွဲချိတ်ရန်"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"တည်ဆောက်မှုနံပါတ်"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"တည်ဆောက်မှုနံပါတ်ကို ကလစ်ဘုတ်သို့ မိတ္တူကူးပြီးပါပြီ။"</string>
</resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 6d6d66f..7ebed82 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Innstillinger"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Forstørringsvindu"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Kontroller for forstørringsvindu"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Zoom inn"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Zoom ut"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Flytt opp"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Flytt ned"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Flytt til venstre"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Flytt til høyre"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Enhetsstyring"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Legg til kontroller for de tilkoblede enhetene dine"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (frakoblet)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Kunne ikke koble til. Prøv på nytt."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Koble til en ny enhet"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Delversjonsnummer"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Delversjonsnummeret er kopiert til utklippstavlen."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index e1dd8c0..6b77bb2 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -339,7 +339,7 @@
<string name="dessert_case" msgid="9104973640704357717">"Dessert Case"</string>
<string name="start_dreams" msgid="9131802557946276718">"स्क्रिन सेभर"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
- <string name="quick_settings_header_onboarding_text" msgid="1918085351115504765">"थप विकल्पहरूका लागि आइकनहरूमा छोइराख्नुहोस्"</string>
+ <string name="quick_settings_header_onboarding_text" msgid="1918085351115504765">"थप विकल्पहरूका लागि आइकनहरूमा टच एण्ड होल्ड गर्नुहोस्"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"बाधा नपुऱ्याउनुहोस्"</string>
<string name="quick_settings_dnd_priority_label" msgid="6251076422352664571">"प्राथमिकता मात्र"</string>
<string name="quick_settings_dnd_alarms_label" msgid="1241780970469630835">"अलार्महरू मात्र"</string>
@@ -591,16 +591,16 @@
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"असक्षम पार्नुहोस्"</string>
<string name="accessibility_output_chooser" msgid="7807898688967194183">"आउटपुट यन्त्र बदल्नुहोस्"</string>
<string name="screen_pinning_title" msgid="9058007390337841305">"एप पिन गरिएको छ"</string>
- <string name="screen_pinning_description" msgid="8699395373875667743">"तपाईंले अनपिन नगरेसम्म यसले त्यसलाई दृश्यमा कायम राख्छ। अनपिन गर्न पछाडि र परिदृश्य बटनलाई छोइराख्नुहोस्।"</string>
- <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"तपाईंले अनपिन नगरेसम्म यसले त्यसलाई दृश्यमा कायम राख्छ। अनपिन गर्न पछाडि र गृह नामक बटनहरूलाई छोइराख्नुहोस्।"</string>
+ <string name="screen_pinning_description" msgid="8699395373875667743">"तपाईंले अनपिन नगरेसम्म यसले त्यसलाई दृश्यमा कायम राख्छ। अनपिन गर्न पछाडि र परिदृश्य बटनलाई टच एण्ड होल्ड गर्नुहोस्।"</string>
+ <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"तपाईंले अनपिन नगरेसम्म यसले त्यसलाई दृश्यमा कायम राख्छ। अनपिन गर्न पछाडि र गृह नामक बटनहरूलाई टच एण्ड होल्ड गर्नुहोस्।"</string>
<string name="screen_pinning_description_gestural" msgid="7246323931831232068">"तपाईंले यो एप अनपिन नगरेसम्म यो एप यहाँ देखिइरहने छ। अनपिन गर्न माथितिर स्वाइप गरी होल्ड गर्नुहोस्।"</string>
- <string name="screen_pinning_description_accessible" msgid="7386449191953535332">"तपाईंले अनपिन नगरेसम्म यसले त्यसलाई दृश्यमा कायम राख्छ। अनपिन गर्न परिदृश्य बटनलाई छोइराख्नुहोस्।"</string>
- <string name="screen_pinning_description_recents_invisible_accessible" msgid="2857071808674481986">"तपाईंले अनपिन नगरेसम्म यसले त्यसलाई दृश्यमा कायम राख्छ। अनपिन गर्न गृह नामक बटनलाई छोइराख्नुहोस्।"</string>
+ <string name="screen_pinning_description_accessible" msgid="7386449191953535332">"तपाईंले अनपिन नगरेसम्म यसले त्यसलाई दृश्यमा कायम राख्छ। अनपिन गर्न परिदृश्य बटनलाई टच एण्ड होल्ड गर्नुहोस्।"</string>
+ <string name="screen_pinning_description_recents_invisible_accessible" msgid="2857071808674481986">"तपाईंले अनपिन नगरेसम्म यसले त्यसलाई दृश्यमा कायम राख्छ। अनपिन गर्न गृह नामक बटनलाई टच एण्ड होल्ड गर्नुहोस्।"</string>
<string name="screen_pinning_exposes_personal_data" msgid="8189852022981524789">"स्क्रिनमा व्यक्तिगत डेटा (जस्तै सम्पर्क ठेगाना र इमेलको सामग्री) देखिन सक्छ।"</string>
<string name="screen_pinning_can_open_other_apps" msgid="7529756813231421455">"पिन गरिएको एपले अन्य एप खोल्न सक्छ।"</string>
- <string name="screen_pinning_toast" msgid="8177286912533744328">"यो एप अनपनि गर्न पछाडि र विवरण नामक बटनहरूलाई छोइराख्नुहोस्"</string>
- <string name="screen_pinning_toast_recents_invisible" msgid="6850978077443052594">"यो एप अनपनि गर्न पछाडि र होम बटनलाई छोइराख्नुहोस्"</string>
- <string name="screen_pinning_toast_gesture_nav" msgid="170699893395336705">"यो एप अनपिन गर्न माथितिर स्वाइप गरी स्क्रिनमा छोइराख्नुहोस्"</string>
+ <string name="screen_pinning_toast" msgid="8177286912533744328">"यो एप अनपनि गर्न पछाडि र विवरण नामक बटनहरूलाई टच एण्ड होल्ड गर्नुहोस्"</string>
+ <string name="screen_pinning_toast_recents_invisible" msgid="6850978077443052594">"यो एप अनपनि गर्न पछाडि र होम बटनलाई टच एण्ड होल्ड गर्नुहोस्"</string>
+ <string name="screen_pinning_toast_gesture_nav" msgid="170699893395336705">"यो एप अनपिन गर्न माथितिर स्वाइप गरी स्क्रिनमा टच एण्ड होल्ड गर्नुहोस्"</string>
<string name="screen_pinning_positive" msgid="3285785989665266984">"बुझेँ"</string>
<string name="screen_pinning_negative" msgid="6882816864569211666">"धन्यवाद पर्दैन"</string>
<string name="screen_pinning_start" msgid="7483998671383371313">"एप पिन गरियो"</string>
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"सेटिङ"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"म्याग्निफिकेसन विन्डो"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"म्याग्निफिकेसन विन्डोका नियन्त्रणहरू"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"जुम इन गर्नुहोस्"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"जुम आउट गर्नुहोस्"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"माथि सार्नुहोस्"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"तल सार्नुहोस्"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"बायाँ सार्नुहोस्"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"दायाँ सार्नुहोस्"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"यन्त्र नियन्त्रण गर्ने विजेटहरू"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"आफ्ना जोडिएका यन्त्रहरूका लागि नियन्त्रण सुविधाहरू थप्नुहोस्"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (डिस्कनेक्ट गरिएको)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"कनेक्ट गर्न सकिएन। फेरि प्रयास गर्नुहोस्।"</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"नयाँ यन्त्रको जोडा बनाउनुहोस्"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"बिल्ड नम्बर"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"बिल्ड नम्बर कपी गरी क्लिपबोर्डमा सारियो।"</string>
</resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index e2db22c..19e1537 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Instellingen"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Vergrotingsvenster"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Bediening van vergrotingsvenster"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Inzoomen"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Uitzoomen"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Omhoog verplaatsen"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Omlaag verplaatsen"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Naar links verplaatsen"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Naar rechts verplaatsen"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Apparaatbediening"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Bedieningselementen voor je gekoppelde apparaten toevoegen"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (verbinding verbroken)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Kan geen verbinding maken. Probeer het nog eens."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Nieuw apparaat koppelen"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Build-nummer"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Build-nummer naar klembord gekopieerd."</string>
</resources>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 970e61c..d4e723f 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"ସେଟିଂସ୍"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"ମ୍ୟାଗ୍ନିଫିକେସନ୍ ୱିଣ୍ଡୋ"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"ମ୍ୟାଗ୍ନିଫିକେସନ୍ ୱିଣ୍ଡୋ ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକ"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"ଜୁମ୍ ଇନ୍ କରନ୍ତୁ"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"ଜୁମ୍ ଆଉଟ୍ କରନ୍ତୁ"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"ଉପରକୁ ମୁଭ୍ କରନ୍ତୁ"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"ତଳକୁ ମୁଭ୍ କରନ୍ତୁ"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"ବାମକୁ ମୁଭ୍ କରନ୍ତୁ"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"ଡାହାଣକୁ ମୁଭ୍ କରନ୍ତୁ"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"ଡିଭାଇସ୍ ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକ"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"ଆପଣଙ୍କ ସଂଯୁକ୍ତ ଡିଭାଇସଗୁଡ଼ିକ ପାଇଁ ନିୟନ୍ତ୍ରଣ ଯୋଗ କରନ୍ତୁ"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (ବିଚ୍ଛିନ୍ନ କରାଯାଇଛି)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"ସଂଯୋଗ କରାଯାଇପାରିଲା ନାହିଁ। ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"ନୂଆ ଡିଭାଇସକୁ ପେୟାର୍ କରନ୍ତୁ"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"ବିଲ୍ଡ ନମ୍ୱର"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"କ୍ଲିପବୋର୍ଡକୁ କପି କରାଯାଇଥିବା ବିଲ୍ଡ ନମ୍ୱର।"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 690d6e5b..19715c5 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"ਸੈਟਿੰਗਾਂ"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"ਵੱਡਦਰਸ਼ੀਕਰਨ Window"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"ਵੱਡਦਰਸ਼ੀਕਰਨ Window ਦੇ ਕੰਟਰੋਲ"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"ਜ਼ੂਮ ਵਧਾਓ"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"ਜ਼ੂਮ ਘਟਾਓ"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"ਉੱਪਰ ਲਿਜਾਓ"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"ਹੇਠਾਂ ਲਿਜਾਓ"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"ਖੱਬੇ ਲਿਜਾਓ"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"ਸੱਜੇ ਲਿਜਾਓ"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"ਡੀਵਾਈਸ ਕੰਟਰੋਲ"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"ਆਪਣੇ ਕਨੈਕਟ ਕੀਤੇ ਡੀਵਾਈਸਾਂ ਲਈ ਕੰਟਰੋਲ ਸ਼ਾਮਲ ਕਰੋ"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (ਡਿਸਕਨੈਕਟ ਹੋਇਆ)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"ਕਨੈਕਟ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"ਨਵਾਂ ਡੀਵਾਈਸ ਜੋੜਾਬੱਧ ਕਰੋ"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"ਬਿਲਡ ਨੰਬਰ"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"ਬਿਲਡ ਨੰਬਰ ਨੂੰ ਕਲਿੱਪਬੋਰਡ \'ਤੇ ਕਾਪੀ ਕੀਤਾ ਗਿਆ।"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 9b31c52..810ea37 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -1022,17 +1022,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Ustawienia"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Okno powiększenia"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Elementy sterujące okna powiększenia"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Powiększ"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Pomniejsz"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Przesuń w górę"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Przesuń w dół"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Przesuń w lewo"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Przesuń w prawo"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Sterowanie urządzeniami"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Dodaj elementy sterujące połączonymi urządzeniami"</string>
@@ -1099,8 +1101,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (rozłączono)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Nie udało się połączyć. Spróbuj ponownie."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Sparuj nowe urządzenie"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Numer kompilacji"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Numer kompilacji został skopiowany do schowka."</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index b76ebda..f8cf881 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -1018,6 +1018,10 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Mover para baixo"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Mover para a esquerda"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Mover para a direita"</string>
+ <string name="magnification_mode_switch_description" msgid="2698364322069934733">"Chave de ampliação"</string>
+ <string name="magnification_mode_switch_state_full_screen" msgid="2882507327576770574">"Ampliar toda a tela"</string>
+ <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Ampliar parte da tela"</string>
+ <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Trocar"</string>
<string name="quick_controls_title" msgid="6839108006171302273">"Controles do dispositivo"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Adiciona controles aos dispositivos conectados"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Configurar controles do dispositivo"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 089bbd4..966f15c 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Definições"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Janela de ampliação"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Controlos da janela de ampliação"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Aumentar zoom"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Diminuir zoom"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Mover para cima"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Mover para baixo"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Mover para a esquerda"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Mover para a direita"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Controlos de dispositivos"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Adicione controlos para os dispositivos associados."</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (desligado)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Não foi possível ligar. Tente novamente."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Sincronize o novo dispositivo"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Número da compilação"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Número da compilação copiado para a área de transferência."</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index b76ebda..f8cf881 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -1018,6 +1018,10 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Mover para baixo"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Mover para a esquerda"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Mover para a direita"</string>
+ <string name="magnification_mode_switch_description" msgid="2698364322069934733">"Chave de ampliação"</string>
+ <string name="magnification_mode_switch_state_full_screen" msgid="2882507327576770574">"Ampliar toda a tela"</string>
+ <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Ampliar parte da tela"</string>
+ <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Trocar"</string>
<string name="quick_controls_title" msgid="6839108006171302273">"Controles do dispositivo"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Adiciona controles aos dispositivos conectados"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Configurar controles do dispositivo"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 3194b9f..07653f1 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -1017,17 +1017,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Setări"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Fereastra de mărire"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Comenzi pentru fereastra de mărire"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Măriți"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Micșorați"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Deplasați în sus"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Deplasați în jos"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Deplasați spre stânga"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Deplasați spre dreapta"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Comenzile dispozitivelor"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Adăugați comenzi pentru dispozitivele conectate"</string>
@@ -1093,8 +1095,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (s-a deconectat)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Nu s-a putut conecta. Reîncercați."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Asociați un nou dispozitiv"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Numărul versiunii"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Numărul versiunii s-a copiat în clipboard."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 26e3433..5f9f115 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -1022,17 +1022,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Настройки"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Окно увеличения"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Настройки окна увеличения"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Увеличить"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Уменьшить"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Переместить вверх"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Переместить вниз"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Переместить влево"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Переместить вправо"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Управление устройствами"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Добавьте виджеты для управления устройствами."</string>
@@ -1099,8 +1101,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (отключено)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Не удалось подключиться. Повторите попытку."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Подключить новое устройство"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Номер сборки"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Номер сборки скопирован в буфер обмена."</string>
</resources>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 8eea1ed..64e24be 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"සැකසීම්"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"විශාලන කවුළුව"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"විශාලනය කිරීමේ කවුළු පාලන"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"විශාලනය වැඩි කරන්න"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"විශාලනය අඩු කරන්න"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"ඉහළට ගෙන යන්න"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"පහළට ගෙන යන්න"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"වමට ගෙන යන්න"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"දකුණට ගෙන යන්න"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"උපාංග පාලන"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"ඔබේ සම්බන්ධිත උපාංග සඳහා පාලන එක් කරන්න"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (විසන්ධි විය)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"සම්බන්ධ වීමට නොහැකි විය. නැවත උත්සාහ කරන්න."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"නව උපාංගය යුගල කරන්න"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"නිමැවුම් අංකය"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"නිමැවුම් අංකය පසුරු පුවරුවට පිටපත් කරන ලදි."</string>
</resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 47045d8..bb75f8f 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -1022,17 +1022,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Nastavenia"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Okno priblíženia"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Ovládacie prvky okna priblíženia"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Priblížiť"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Oddialiť"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Posunúť nahor"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Posunúť nadol"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Posunúť doľava"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Posunúť doprava"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Ovládanie zariadení"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Pridajte si ovládače pripojených zariadení"</string>
@@ -1099,8 +1101,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (odpojené)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Nepodarilo sa pripojiť. Skúste to znova."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Spárovať nové zariadenie"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Číslo zostavy"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Číslo zostavy bolo skopírované do schránky."</string>
</resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 7b68a3a..98abf37 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -1022,17 +1022,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Nastavitve"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Povečevalno okno"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Kontrolniki povečevalnega okna"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Povečaj"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Pomanjšaj"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Premakni navzgor"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Premakni navzdol"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Premakni levo"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Premakni desno"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Kontrolniki naprave"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Dodajte kontrolnike za povezane naprave"</string>
@@ -1099,8 +1101,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (povezava prekinjena)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Povezave ni bilo mogoče vzpostaviti. Poskusite znova."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Seznanitev nove naprave"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Delovna različica"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Delovna različica je bila kopirana v odložišče."</string>
</resources>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index b7ebb2a..154d53d 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Cilësimet"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Dritarja e zmadhimit"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Kontrollet e dritares së zmadhimit"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Zmadho"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Zvogëlo"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Lëvize lart"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Lëvize poshtë"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Lëvize majtas"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Lëvize djathtas"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Kontrollet e pajisjes"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Shto kontrolle për pajisjet e tua të lidhura"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (e shkëputur)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Nuk mund të lidhej. Provo sërish."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Çifto pajisjen e re"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Numri i ndërtimit"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Numri i ndërtimit u kopjua te kujtesa e fragmenteve"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index b6a90cd..e59c0bb 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -1017,17 +1017,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Подешавања"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Прозор за увећање"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Контроле прозора за увећање"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Увећајте"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Умањите"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Померите нагоре"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Померите надоле"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Померите налево"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Померите надесно"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Контроле уређаја"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Додајте контроле за повезане уређаје"</string>
@@ -1093,8 +1095,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (веза је прекинута)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Повезивање није успело. Пробајте поново."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Упари нови уређај"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Број верзије"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Број верзије је копиран у привремену меморију."</string>
</resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 890f504..8213118 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Inställningar"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Förstoringsfönster"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Inställningar för förstoringsfönster"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Zooma in"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Zooma ut"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Flytta uppåt"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Flytta nedåt"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Flytta åt vänster"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Flytta åt höger"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Enhetsstyrning"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Lägg till snabbkontroller för anslutna enheter"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (frånkopplad)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Det gick inte att ansluta. Försök igen."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Parkoppla en ny enhet"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Versionsnummer"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Versionsnumret har kopierats till urklipp."</string>
</resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 34042ad..0a0e91a 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Mipangilio"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Dirisha la Ukuzaji"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Vidhibiti vya Dirisha la Ukuzaji"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Vuta karibu"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Sogeza mbali"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Sogeza juu"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Sogeza chini"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Sogeza kushoto"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Sogeza kulia"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Vidhibiti vya vifaa"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Weka vidhibiti vya vifaa ulivyounganisha"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (hakijaunganishwa)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Imeshindwa kuunganisha. Jaribu tena."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Oanisha kifaa kipya"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Nambari ya muundo"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Nambari ya muundo imewekwa kwenye ubao wa kunakili."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index b30859f..27a9d06 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"அமைப்புகள்"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"பெரிதாக்கல் சாளரம்"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"பெரிதாக்கல் சாளரக் கட்டுப்பாடுகள்"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"பெரிதாக்கு"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"சிறிதாக்கு"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"மேலே நகர்த்து"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"கீழே நகர்த்து"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"இடப்புறம் நகர்த்து"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"வலப்புறம் நகர்த்து"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"சாதனக் கட்டுப்பாடுகள்"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"இணைக்கப்பட்ட சாதனங்களில் கட்டுப்பாடுகளைச் சேர்க்கலாம்"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (இணைப்பு துண்டிக்கப்பட்டது)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"இணைக்க முடியவில்லை. மீண்டும் முயலவும்."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"புதிய சாதனத்தை இணைத்தல்"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"பதிப்பு எண்"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"பதிப்பு எண் கிளிப்போர்டுக்கு நகலெடுக்கப்பட்டது."</string>
</resources>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index cb134a1..5e35a5c 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"సెట్టింగ్లు"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"మాగ్నిఫికేషన్ విండో"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"మాగ్నిఫికేషన్ నియంత్రణల విండో"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"దగ్గరగా జూమ్ చేయండి"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"దూరంగా జూమ్ చేయండి"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"పైకి పంపండి"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"కిందకి పంపండి"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"ఎడమవైపుగా జరపండి"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"కుడివైపుగా జరపండి"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"పరికరం నియంత్రణలు"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"మీ కనెక్ట్ అయిన పరికరాలకు నియంత్రణలను జోడించండి"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (డిస్కనెక్ట్ అయ్యింది)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"కనెక్ట్ చేయడం సాధ్యపడలేదు. మళ్లీ ట్రై చేయండి."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"కొత్త పరికరాన్ని పెయిర్ చేయండి"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"బిల్డ్ నంబర్"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"బిల్డ్ నంబర్, క్లిప్బోర్డ్కు కాపీ చేయబడింది."</string>
</resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index d678353..3f7e0da 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"การตั้งค่า"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"หน้าต่างการขยาย"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"การควบคุมหน้าต่างการขยาย"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"ซูมเข้า"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"ซูมออก"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"ย้ายขึ้น"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"ย้ายลง"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"ย้ายไปทางซ้าย"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"ย้ายไปทางขวา"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"ระบบควบคุมอุปกรณ์"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"เพิ่มตัวควบคุมของอุปกรณ์ที่เชื่อมต่อ"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (ยกเลิกการเชื่อมต่อแล้ว)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"เชื่อมต่อไม่ได้ ลองใหม่"</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"จับคู่อุปกรณ์ใหม่"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"หมายเลขบิวด์"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"คัดลอกหมายเลขบิวด์ไปยังคลิปบอร์ดแล้ว"</string>
</resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 21fdd31..d03f0f8 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Mga Setting"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Window ng Pag-magnify"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Mga Kontrol sa Pag-magnify ng Window"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Mag-zoom in"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Mag-zoom out"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Itaas"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Ibaba"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Ilipat pakaliwa"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Ilipat pakanan"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Mga kontrol ng device"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Magdagdag ng kontrol para sa mga nakakonektang device"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (nakadiskonekta)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Hindi makakonekta. Subukan ulit."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Magpares ng bagong device"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Numero ng build"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Nakopya sa clipboard ang numero ng build."</string>
</resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 3e04d19..62f3671 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Ayarlar"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Büyütme Penceresi"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Büyütme Penceresi Kontrolleri"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Yakınlaştır"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Uzaklaştır"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Yukarı taşı"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Aşağı taşı"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Sola taşı"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Sağa taşı"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Cihaz denetimleri"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Bağlı cihazlarınız için denetimler ekleyin"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (bağlı değil)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Bağlanılamadı. Tekrar deneyin."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Yeni cihaz eşle"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Derleme numarası"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Derleme numarası panoya kopyalandı."</string>
</resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index a7c6bef..069577f 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -1022,17 +1022,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Налаштування"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Вікно збільшення"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Елементи керування вікна збільшення"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Наблизити"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Віддалити"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Перемістити вгору"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Перемістити вниз"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Перемістити ліворуч"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Перемістити праворуч"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Керування пристроями"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Додайте елементи керування для підключених пристроїв"</string>
@@ -1099,8 +1101,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (відключено)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Не вдалося підключитися. Повторіть спробу."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Підключити новий пристрій"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Номер складання"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Номер складання скопійовано в буфер обміну."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index f24492c..ffba2bd 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"ترتیبات"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"میگنیفکیشن ونڈو"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"میگنیفکیشن ونڈو کنٹرولز"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"زوم ان کریں"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"زوم آؤٹ کریں"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"اوپر منتقل کریں"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"نیچے منتقل کریں"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"بائیں منتقل کریں"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"دائیں منتقل کریں"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"آلہ کے کنٹرولز"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"اپنے منسلک آلات کے لیے کنٹرولز شامل کریں"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (غیر منسلک ہو گیا)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"منسلک نہیں ہو سکا۔ پھر کوشش کریں۔"</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"نئے آلہ کا جوڑا بنائیں"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"بلڈ نمبر"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"بلڈ نمبر کلپ بورڈ میں کاپی ہو گیا۔"</string>
</resources>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 32c2406..433eadb 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Sozlamalar"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Kattalashtirish oynasi"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Kattalashtirish oynasi sozlamalari"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Yaqinlashtirish"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Uzoqlashtirish"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Tepaga siljitish"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Pastga siljitish"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Chapga siljitish"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Oʻngga siljitish"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Qurilmalarni boshqarish"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Ulangan qurilmalar uchun boshqaruv elementlari"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (uzilgan)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Ulanmadi. Qayta urining."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Yangi qurilmani ulash"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Nashr raqami"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Nashr raqami vaqtinchalik xotiraga nusxalandi."</string>
</resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index d9c80df..e337c42 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Cài đặt"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Cửa sổ phóng to"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Các tùy chọn điều khiển cửa sổ phóng to"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Phóng to"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Thu nhỏ"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Di chuyển lên"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Di chuyển xuống"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Di chuyển sang trái"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Di chuyển sang phải"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Điều khiển thiết bị"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Thêm các tùy chọn điều khiển cho các thiết bị đã kết nối của bạn"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (đã ngắt kết nối)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Không thể kết nối. Hãy thử lại."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Ghép nối thiết bị mới"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Số bản dựng"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Đã sao chép số bản dựng vào khay nhớ tạm."</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 9f9424d..254d974 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"设置"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"放大窗口"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"放大窗口控件"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"放大"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"缩小"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"上移"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"下移"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"左移"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"右移"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"设备控制器"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"为您所连接的设备添加控件"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>(已断开连接)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"无法连接。请重试。"</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"与新设备配对"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"版本号"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"已将版本号复制到剪贴板。"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 2825a9e..e8afc0e 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"設定"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"放大視窗"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"放大視窗控制項"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"放大"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"縮細"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"向上移"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"向下移"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"向左移"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"向右移"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"裝置控制"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"為連接的裝置新增控制選項"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (已中斷連線)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"無法連線,請再試一次。"</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"配對新裝置"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"版本號碼"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"版本號碼已複製到剪貼簿。"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 8acf2c6..0fc7db6 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"設定"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"放大視窗"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"放大視窗控制項"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"放大"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"縮小"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"向上移"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"向下移"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"向左移"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"向右移"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"裝置控制"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"新增已連結裝置的控制項"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (已中斷連線)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"無法連線,請再試一次。"</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"配對新裝置"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"版本號碼"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"已將版本號碼複製到剪貼簿。"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 4935206..3ada5cc 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -1012,17 +1012,19 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Amasethingi"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Iwindi Lesikhulisi"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Izilawuli Zewindi Lesikhulisi"</string>
- <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Sondeza"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Hlehlisa"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Khuphula"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Yehlisa"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Yisa kwesokunxele"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Yisa kwesokudla"</string>
+ <!-- no translation found for magnification_mode_switch_description (2698364322069934733) -->
<skip />
- <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <!-- no translation found for magnification_mode_switch_state_full_screen (2882507327576770574) -->
<skip />
- <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <!-- no translation found for magnification_mode_switch_state_window (8597100249594076965) -->
<skip />
- <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
- <skip />
- <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
- <skip />
- <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <!-- no translation found for magnification_mode_switch_click_label (2786203505805898199) -->
<skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Izilawuli zezinsiza"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Engeza izilawuli zedivayisi yakho exhunyiwe"</string>
@@ -1087,8 +1089,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (inqamukile)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Ayikwazanga ukuxhumeka. Zama futhi."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Bhanqa idivayisi entsha"</string>
- <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
- <skip />
- <!-- no translation found for build_number_copy_toast (877720921605503046) -->
- <skip />
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Yakha inombolo"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Yakha inombolo ekopishelwe kubhodi yokunamathisela."</string>
</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 6bada51..d1fb6cd 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -218,7 +218,7 @@
<!-- Notification ticker displayed when a screenshot is being saved to the Gallery. [CHAR LIMIT=30] -->
<string name="screenshot_saving_ticker">Saving screenshot\u2026</string>
- <!-- Notification title displayed when a screenshot is being saved to the Gallery. [CHAR LIMIT=50] -->
+ <!-- Informs the user that a screenshot is being saved. [CHAR LIMIT=50] -->
<string name="screenshot_saving_title">Saving screenshot\u2026</string>
<!-- Notification title displayed when a screenshot is saved to the Gallery. [CHAR LIMIT=50] -->
<string name="screenshot_saved_title">Screenshot saved</string>
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index f24644b..9f28e09 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -47,6 +47,7 @@
import com.android.systemui.fragments.FragmentService;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.keyguard.WakefulnessLifecycle;
+import com.android.systemui.media.dialog.MediaOutputDialogFactory;
import com.android.systemui.model.SysUiState;
import com.android.systemui.navigationbar.NavigationBarController;
import com.android.systemui.navigationbar.NavigationModeController;
@@ -344,6 +345,7 @@
@Inject Lazy<DisplayImeController> mDisplayImeController;
@Inject Lazy<RecordingController> mRecordingController;
@Inject Lazy<ProtoTracer> mProtoTracer;
+ @Inject Lazy<MediaOutputDialogFactory> mMediaOutputDialogFactory;
@Inject
public Dependency() {
@@ -541,6 +543,8 @@
mProviders.put(RecordingController.class, mRecordingController::get);
+ mProviders.put(MediaOutputDialogFactory.class, mMediaOutputDialogFactory::get);
+
Dependency.setInstance(this);
}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java
index 1af3897..69a0d65 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java
@@ -46,9 +46,15 @@
*/
class MagnificationModeSwitch {
- private static final int DURATION_MS = 5000;
- private static final int START_DELAY_MS = 3000;
- private final Runnable mAnimationTask;
+ @VisibleForTesting
+ static final long FADING_ANIMATION_DURATION_MS = 300;
+ private static final int DEFAULT_FADE_OUT_ANIMATION_DELAY_MS = 3000;
+ // The button visible duration starting from the last showButton() called.
+ private int mVisibleDuration = DEFAULT_FADE_OUT_ANIMATION_DELAY_MS;
+ private final Runnable mFadeInAnimationTask;
+ private final Runnable mFadeOutAnimationTask;
+ @VisibleForTesting
+ boolean mIsFadeOutAnimating = false;
private final Context mContext;
private final WindowManager mWindowManager;
@@ -100,12 +106,19 @@
}
});
- mAnimationTask = () -> {
+ mFadeInAnimationTask = () -> {
+ mImageView.animate()
+ .alpha(1f)
+ .setDuration(FADING_ANIMATION_DURATION_MS)
+ .start();
+ };
+ mFadeOutAnimationTask = () -> {
mImageView.animate()
.alpha(0f)
- .setDuration(DURATION_MS)
+ .setDuration(FADING_ANIMATION_DURATION_MS)
.withEndAction(() -> removeButton())
.start();
+ mIsFadeOutAnimating = true;
};
}
@@ -128,7 +141,6 @@
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
- mImageView.setAlpha(1.0f);
mImageView.animate().cancel();
mLastDown.set(event.getRawX(), event.getRawY());
mLastDrag.set(event.getRawX(), event.getRawY());
@@ -169,9 +181,13 @@
if (!mIsVisible) {
return;
}
- mImageView.animate().cancel();
- mWindowManager.removeView(mImageView);
// Reset button status.
+ mImageView.removeCallbacks(mFadeInAnimationTask);
+ mImageView.removeCallbacks(mFadeOutAnimationTask);
+ mImageView.animate().cancel();
+ mIsFadeOutAnimating = false;
+ mImageView.setAlpha(0f);
+ mWindowManager.removeView(mImageView);
mIsVisible = false;
mParams.x = 0;
mParams.y = 0;
@@ -185,14 +201,15 @@
if (!mIsVisible) {
mWindowManager.addView(mImageView, mParams);
mIsVisible = true;
+ mImageView.postOnAnimation(mFadeInAnimationTask);
}
- mImageView.setAlpha(1.0f);
- // TODO(b/143852371): use accessibility timeout as a delay.
- // Dismiss the magnification switch button after the button is displayed for a period of
- // time.
- mImageView.animate().cancel();
- mImageView.removeCallbacks(mAnimationTask);
- mImageView.postDelayed(mAnimationTask, START_DELAY_MS);
+ if (mIsFadeOutAnimating) {
+ mImageView.animate().cancel();
+ mImageView.setAlpha(1f);
+ }
+ // Refresh the time slot of the fade-out task whenever this method is called.
+ mImageView.removeCallbacks(mFadeOutAnimationTask);
+ mImageView.postOnAnimationDelayed(mFadeOutAnimationTask, mVisibleDuration);
}
void onConfigurationChanged(int configDiff) {
@@ -222,6 +239,7 @@
imageView.setClickable(true);
imageView.setFocusable(true);
imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
+ imageView.setAlpha(0f);
return imageView;
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index c409d87..e3b0049 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -63,7 +63,7 @@
* Note that the current architecture is designed so that a single {@link UdfpsController}
* controls/manages all UDFPS sensors. In other words, a single controller is registered with
* {@link com.android.server.biometrics.sensors.fingerprint.FingerprintService}, and interfaces such
- * as {@link FingerprintManager#onFingerDown(int, int, int, float, float)} or
+ * as {@link FingerprintManager#onPointerDown(int, int, int, float, float)} or
* {@link IUdfpsOverlayController#showUdfpsOverlay(int)}should all have
* {@code sensorId} parameters.
*/
@@ -374,7 +374,7 @@
fw.write(mHbmEnableCommand);
fw.close();
}
- mFingerprintManager.onFingerDown(mUdfpsSensorId, x, y, minor, major);
+ mFingerprintManager.onPointerDown(mUdfpsSensorId, x, y, minor, major);
} catch (IOException e) {
mView.hideScrimAndDot();
Log.e(TAG, "onFingerDown | failed to enable HBM: " + e.getMessage());
@@ -382,7 +382,7 @@
}
private void onFingerUp() {
- mFingerprintManager.onFingerUp(mUdfpsSensorId);
+ mFingerprintManager.onPointerUp(mUdfpsSensorId);
// Hiding the scrim before disabling HBM results in less noticeable flicker.
mView.hideScrimAndDot();
if (mHbmSupported) {
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
index 83a816b..3af36a9 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
@@ -30,6 +30,7 @@
import static com.android.systemui.bubbles.BubbleDebugConfig.DEBUG_BUBBLE_EXPANDED_VIEW;
import static com.android.systemui.bubbles.BubbleDebugConfig.TAG_BUBBLES;
import static com.android.systemui.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.systemui.bubbles.BubbleOverflowActivity.EXTRA_BUBBLE_CONTROLLER;
import android.annotation.NonNull;
import android.annotation.SuppressLint;
@@ -51,6 +52,7 @@
import android.graphics.drawable.ShapeDrawable;
import android.hardware.display.VirtualDisplay;
import android.os.Binder;
+import android.os.Bundle;
import android.os.RemoteException;
import android.util.AttributeSet;
import android.util.Log;
@@ -576,6 +578,9 @@
mIsOverflow = overflow;
Intent target = new Intent(mContext, BubbleOverflowActivity.class);
+ Bundle extras = new Bundle();
+ extras.putBinder(EXTRA_BUBBLE_CONTROLLER, ObjectWrapper.wrap(mBubbles));
+ target.putExtras(extras);
mPendingIntent = PendingIntent.getActivity(mContext, /* requestCode */ 0,
target, PendingIntent.FLAG_UPDATE_CURRENT);
mSettingsIcon.setVisibility(GONE);
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java
index 5fdda97..fc3f5b6 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java
@@ -22,11 +22,13 @@
import android.app.Activity;
import android.content.Context;
+import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.os.Bundle;
+import android.os.IBinder;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.LayoutInflater;
@@ -47,13 +49,14 @@
import java.util.List;
import java.util.function.Consumer;
-import javax.inject.Inject;
/**
* Activity for showing aged out bubbles.
* Must be public to be accessible to androidx...AppComponentFactory
*/
public class BubbleOverflowActivity extends Activity {
+ static final String EXTRA_BUBBLE_CONTROLLER = "bubble_controller";
+
private static final String TAG = TAG_WITH_CLASS_NAME ? "BubbleOverflowActivity" : TAG_BUBBLES;
private LinearLayout mEmptyState;
@@ -93,11 +96,6 @@
}
}
- @Inject
- public BubbleOverflowActivity(Bubbles bubbles) {
- mBubbles = bubbles;
- }
-
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -109,6 +107,15 @@
mEmptyStateSubtitle = findViewById(R.id.bubble_overflow_empty_subtitle);
mEmptyStateImage = findViewById(R.id.bubble_overflow_empty_state_image);
+ Intent intent = getIntent();
+ if (intent != null && intent.getExtras() != null) {
+ IBinder binder = intent.getExtras().getBinder(EXTRA_BUBBLE_CONTROLLER);
+ if (binder instanceof ObjectWrapper) {
+ mBubbles = ((ObjectWrapper<Bubbles>) binder).get();
+ }
+ } else {
+ Log.w(TAG, "Bubble overflow activity created without bubble controller!");
+ }
updateOverflow();
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/ObjectWrapper.java b/packages/SystemUI/src/com/android/systemui/bubbles/ObjectWrapper.java
new file mode 100644
index 0000000..f054122
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/ObjectWrapper.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.bubbles;
+
+import android.os.Binder;
+import android.os.IBinder;
+
+// Copied from Launcher3
+/**
+ * Utility class to pass non-parcealable objects within same process using parcealable payload.
+ *
+ * It wraps the object in a binder as binders are singleton within a process
+ */
+public class ObjectWrapper<T> extends Binder {
+
+ private T mObject;
+
+ public ObjectWrapper(T object) {
+ mObject = object;
+ }
+
+ public T get() {
+ return mObject;
+ }
+
+ public void clear() {
+ mObject = null;
+ }
+
+ public static IBinder wrap(Object obj) {
+ return new ObjectWrapper<>(obj);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
index b7490a5..4c902b9 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
@@ -72,9 +72,9 @@
/**
* Values to use for the default {@link SpringForce} provided to the physics animation layout.
*/
- public static final int DEFAULT_STIFFNESS = 12000;
+ public static final int SPRING_TO_TOUCH_STIFFNESS = 12000;
public static final float IME_ANIMATION_STIFFNESS = SpringForce.STIFFNESS_LOW;
- private static final int FLING_FOLLOW_STIFFNESS = 500;
+ private static final int CHAIN_STIFFNESS = 600;
public static final float DEFAULT_BOUNCINESS = 0.9f;
private final PhysicsAnimator.SpringConfig mAnimateOutSpringConfig =
@@ -629,7 +629,7 @@
public void moveStackFromTouch(float x, float y) {
// Begin the spring-to-touch catch up animation if needed.
if (mSpringToTouchOnNextMotionEvent) {
- springStack(x, y, DEFAULT_STIFFNESS);
+ springStack(x, y, SPRING_TO_TOUCH_STIFFNESS);
mSpringToTouchOnNextMotionEvent = false;
mFirstBubbleSpringingToTouch = true;
} else if (mFirstBubbleSpringingToTouch) {
@@ -762,14 +762,12 @@
@Override
SpringForce getSpringForce(DynamicAnimation.ViewProperty property, View view) {
final ContentResolver contentResolver = mLayout.getContext().getContentResolver();
- final float stiffness = Settings.Secure.getFloat(contentResolver, "bubble_stiffness",
- mIsMovingFromFlinging ? FLING_FOLLOW_STIFFNESS : DEFAULT_STIFFNESS /* default */);
final float dampingRatio = Settings.Secure.getFloat(contentResolver, "bubble_damping",
DEFAULT_BOUNCINESS);
return new SpringForce()
.setDampingRatio(dampingRatio)
- .setStiffness(stiffness);
+ .setStiffness(CHAIN_STIFFNESS);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java
index ba88a59..d13e194 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java
@@ -19,7 +19,6 @@
import android.app.Activity;
import com.android.systemui.ForegroundServicesDialog;
-import com.android.systemui.bubbles.BubbleOverflowActivity;
import com.android.systemui.keyguard.WorkLockActivity;
import com.android.systemui.screenrecord.ScreenRecordDialog;
import com.android.systemui.settings.BrightnessDialog;
@@ -68,12 +67,6 @@
@ClassKey(ScreenRecordDialog.class)
public abstract Activity bindScreenRecordDialog(ScreenRecordDialog activity);
- /** Inject into BubbleOverflowActivity. */
- @Binds
- @IntoMap
- @ClassKey(BubbleOverflowActivity.class)
- public abstract Activity bindBubbleOverflowActivity(BubbleOverflowActivity activity);
-
/** Inject into UsbDebuggingActivity. */
@Binds
@IntoMap
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
index f6571ef..5b096ea 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
@@ -42,10 +42,10 @@
import androidx.constraintlayout.widget.ConstraintSet;
import com.android.settingslib.Utils;
-import com.android.settingslib.media.MediaOutputSliceConstants;
import com.android.settingslib.widget.AdaptiveIcon;
import com.android.systemui.R;
import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.media.dialog.MediaOutputDialogFactory;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
import com.android.systemui.util.animation.TransitionLayout;
@@ -93,7 +93,7 @@
private int mAlbumArtRadius;
// This will provide the corners for the album art.
private final ViewOutlineProvider mViewOutlineProvider;
-
+ private final MediaOutputDialogFactory mMediaOutputDialogFactory;
/**
* Initialize a new control panel
* @param context
@@ -104,7 +104,8 @@
public MediaControlPanel(Context context, @Background Executor backgroundExecutor,
ActivityStarter activityStarter, MediaViewController mediaViewController,
SeekBarViewModel seekBarViewModel, Lazy<MediaDataManager> lazyMediaDataManager,
- KeyguardDismissUtil keyguardDismissUtil) {
+ KeyguardDismissUtil keyguardDismissUtil, MediaOutputDialogFactory
+ mediaOutputDialogFactory) {
mContext = context;
mBackgroundExecutor = backgroundExecutor;
mActivityStarter = activityStarter;
@@ -112,6 +113,7 @@
mMediaViewController = mediaViewController;
mMediaDataManagerLazy = lazyMediaDataManager;
mKeyguardDismissUtil = keyguardDismissUtil;
+ mMediaOutputDialogFactory = mediaOutputDialogFactory;
loadDimens();
mViewOutlineProvider = new ViewOutlineProvider() {
@@ -273,13 +275,7 @@
setVisibleAndAlpha(collapsedSet, R.id.media_seamless, true /*visible */);
setVisibleAndAlpha(expandedSet, R.id.media_seamless, true /*visible */);
mViewHolder.getSeamless().setOnClickListener(v -> {
- final Intent intent = new Intent()
- .setAction(MediaOutputSliceConstants.ACTION_MEDIA_OUTPUT)
- .putExtra(MediaOutputSliceConstants.EXTRA_PACKAGE_NAME,
- data.getPackageName())
- .putExtra(MediaOutputSliceConstants.KEY_MEDIA_SESSION_TOKEN, mToken);
- mActivityStarter.startActivity(intent, false, true /* dismissShade */,
- Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ mMediaOutputDialogFactory.create(data.getPackageName(), true);
});
ImageView iconView = mViewHolder.getSeamlessIcon();
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
index 3b82999..caef536 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
@@ -49,7 +49,7 @@
* Base dialog for media output UI
*/
public abstract class MediaOutputBaseDialog extends SystemUIDialog implements
- MediaOutputController.Callback {
+ MediaOutputController.Callback, Window.Callback {
private static final String TAG = "MediaOutputDialog";
@@ -210,4 +210,12 @@
public void dismissDialog() {
dismiss();
}
+
+ @Override
+ public void onWindowFocusChanged(boolean hasFocus) {
+ super.onWindowFocusChanged(hasFocus);
+ if (!hasFocus && isShowing()) {
+ dismiss();
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
index ac55fa0..7e2433a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
@@ -23,6 +23,7 @@
import android.content.res.Configuration;
import android.graphics.Point;
import android.util.AttributeSet;
+import android.util.Pair;
import android.view.View;
import android.widget.FrameLayout;
@@ -282,7 +283,7 @@
View view = getChildAt(i);
if (view == mStatusBarBackground || view == mBackgroundGradient
|| view == mQSCustomizer) {
- // Some views are always full width
+ // Some views are always full width or have dependent padding
continue;
}
LayoutParams lp = (LayoutParams) view.getLayoutParams();
@@ -291,6 +292,9 @@
if (view == mQSPanelContainer) {
// QS panel lays out some of its content full width
mQSPanel.setContentMargins(mContentPaddingStart, mContentPaddingEnd);
+ Pair<Integer, Integer> margins = mQSPanel.getVisualSideMargins();
+ // Apply paddings based on QSPanel
+ mQSCustomizer.setContentPaddings(margins.first, margins.second);
} else if (view == mHeader) {
// The header contains the QQS panel which needs to have special padding, to
// visually align them.
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index fdc0a60e..ca3e4cf 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -30,6 +30,7 @@
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
+import android.util.Pair;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
@@ -1080,6 +1081,10 @@
updateTileLayoutMargins();
}
+ public Pair<Integer, Integer> getVisualSideMargins() {
+ return new Pair(mVisualMarginStart, mUsingHorizontalLayout ? 0 : mVisualMarginEnd);
+ }
+
private void updateTileLayoutMargins() {
int marginEnd = mVisualMarginEnd;
if (mUsingHorizontalLayout) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
index e5ed88c..55b67e0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -132,6 +132,7 @@
layout.setSpanSizeLookup(mTileAdapter.getSizeLookup());
mRecyclerView.setLayoutManager(layout);
mRecyclerView.addItemDecoration(mTileAdapter.getItemDecoration());
+ mRecyclerView.addItemDecoration(mTileAdapter.getMarginItemDecoration());
DefaultItemAnimator animator = new DefaultItemAnimator();
animator.setMoveDuration(TileAdapter.MOVE_DURATION);
mRecyclerView.setItemAnimator(animator);
@@ -221,6 +222,22 @@
}
}
+ /**
+ * Sets the padding for the RecyclerView. Also, updates the margin between the tiles in the
+ * {@link TileAdapter}.
+ */
+ public void setContentPaddings(int paddingStart, int paddingEnd) {
+ int halfMargin = mContext.getResources()
+ .getDimensionPixelSize(R.dimen.qs_tile_margin_horizontal) / 2;
+ mTileAdapter.changeHalfMargin(halfMargin);
+ mRecyclerView.setPaddingRelative(
+ paddingStart,
+ mRecyclerView.getPaddingTop(),
+ paddingEnd,
+ mRecyclerView.getPaddingBottom()
+ );
+ }
+
private void queryTiles() {
mTileQueryHelper.queryTiles(mHost);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
index e049025..b471dfa 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -18,6 +18,7 @@
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
+import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.view.LayoutInflater;
@@ -75,6 +76,7 @@
private final List<TileInfo> mTiles = new ArrayList<>();
private final ItemTouchHelper mItemTouchHelper;
private final ItemDecoration mDecoration;
+ private final MarginTileDecoration mMarginDecoration;
private final int mMinNumTiles;
private int mEditIndex;
private int mTileDividerIndex;
@@ -97,6 +99,7 @@
mUiEventLogger = uiEventLogger;
mItemTouchHelper = new ItemTouchHelper(mCallbacks);
mDecoration = new TileItemDecoration(context);
+ mMarginDecoration = new MarginTileDecoration();
mMinNumTiles = context.getResources().getInteger(R.integer.quick_settings_min_num_tiles);
mAccessibilityDelegate = new TileAdapterDelegate();
}
@@ -123,6 +126,14 @@
return mDecoration;
}
+ public ItemDecoration getMarginItemDecoration() {
+ return mMarginDecoration;
+ }
+
+ public void changeHalfMargin(int halfMargin) {
+ mMarginDecoration.setHalfMargin(halfMargin);
+ }
+
public void saveSpecs(QSTileHost host) {
List<String> newSpecs = new ArrayList<>();
clearAccessibilityState();
@@ -596,7 +607,6 @@
mDrawable = context.getDrawable(R.drawable.qs_customize_tile_decoration);
}
-
@Override
public void onDraw(Canvas c, RecyclerView parent, State state) {
super.onDraw(c, parent, state);
@@ -630,6 +640,25 @@
}
}
+ private static class MarginTileDecoration extends ItemDecoration {
+ private int mHalfMargin;
+
+ public void setHalfMargin(int halfMargin) {
+ mHalfMargin = halfMargin;
+ }
+
+ @Override
+ public void getItemOffsets(@NonNull Rect outRect, @NonNull View view,
+ @NonNull RecyclerView parent, @NonNull State state) {
+ if (view instanceof TextView) {
+ super.getItemOffsets(outRect, view, parent, state);
+ } else {
+ outRect.left = mHalfMargin;
+ outRect.right = mHalfMargin;
+ }
+ }
+ }
+
private final ItemTouchHelper.Callback mCallbacks = new ItemTouchHelper.Callback() {
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 2b4fa2a..fe32227 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -69,6 +69,7 @@
import android.view.ViewTreeObserver;
import android.view.WindowInsets;
import android.view.WindowManager;
+import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.AnimationUtils;
@@ -104,7 +105,6 @@
public Bitmap image;
public Consumer<Uri> finisher;
public GlobalScreenshot.ActionsReadyListener mActionsReadyListener;
- public int errorMsgResId;
void clearImage() {
image = null;
@@ -184,6 +184,7 @@
private final WindowManager.LayoutParams mWindowLayoutParams;
private final Display mDisplay;
private final DisplayMetrics mDisplayMetrics;
+ private final AccessibilityManager mAccessibilityManager;
private View mScreenshotLayout;
private ScreenshotSelectorView mScreenshotSelectorView;
@@ -242,6 +243,7 @@
mScreenshotSmartActions = screenshotSmartActions;
mNotificationsController = screenshotNotificationsController;
mUiEventLogger = uiEventLogger;
+ mAccessibilityManager = AccessibilityManager.getInstance(mContext);
reloadAssets();
Configuration config = mContext.getResources().getConfiguration();
@@ -573,6 +575,14 @@
private void saveScreenshot(Bitmap screenshot, Consumer<Uri> finisher, Rect screenRect,
Insets screenInsets, boolean showFlash) {
+ if (mAccessibilityManager.isEnabled()) {
+ AccessibilityEvent event =
+ new AccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+ event.setContentDescription(
+ mContext.getResources().getString(R.string.screenshot_saving_title));
+ mAccessibilityManager.sendAccessibilityEvent(event);
+ }
+
if (mScreenshotLayout.isAttachedToWindow()) {
// if we didn't already dismiss for another reason
if (mDismissAnimation == null || !mDismissAnimation.isRunning()) {
@@ -632,7 +642,7 @@
if (imageData.uri == null) {
mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_NOT_SAVED);
mNotificationsController.notifyScreenshotError(
- R.string.screenshot_failed_to_capture_text);
+ R.string.screenshot_failed_to_save_text);
} else {
mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_SAVED);
@@ -752,7 +762,7 @@
if (imageData.uri == null) {
mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_NOT_SAVED);
mNotificationsController.notifyScreenshotError(
- R.string.screenshot_failed_to_capture_text);
+ R.string.screenshot_failed_to_save_text);
} else {
mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_SAVED);
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java b/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
index df1d789..f0ea597 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
@@ -217,13 +217,11 @@
mParams.mActionsReadyListener.onActionsReady(mImageData);
mParams.finisher.accept(mImageData.uri);
mParams.image = null;
- mParams.errorMsgResId = 0;
} catch (Exception e) {
// IOException/UnsupportedOperationException may be thrown if external storage is
// not mounted
Slog.e(TAG, "unable to save screenshot", e);
mParams.clearImage();
- mParams.errorMsgResId = R.string.screenshot_failed_to_save_text;
mImageData.reset();
mParams.mActionsReadyListener.onActionsReady(mImageData);
mParams.finisher.accept(null);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/MediaTransferManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/MediaTransferManager.java
index ac3523b..1b1a51b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/MediaTransferManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/MediaTransferManager.java
@@ -17,7 +17,6 @@
package com.android.systemui.statusbar;
import android.content.Context;
-import android.content.Intent;
import android.content.res.ColorStateList;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
@@ -36,10 +35,9 @@
import com.android.settingslib.media.InfoMediaManager;
import com.android.settingslib.media.LocalMediaManager;
import com.android.settingslib.media.MediaDevice;
-import com.android.settingslib.media.MediaOutputSliceConstants;
import com.android.settingslib.widget.AdaptiveIcon;
import com.android.systemui.Dependency;
-import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.media.dialog.MediaOutputDialogFactory;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -51,7 +49,7 @@
*/
public class MediaTransferManager {
private final Context mContext;
- private final ActivityStarter mActivityStarter;
+ private final MediaOutputDialogFactory mMediaOutputDialogFactory;
private MediaDevice mDevice;
private List<View> mViews = new ArrayList<>();
private LocalMediaManager mLocalMediaManager;
@@ -74,12 +72,7 @@
ViewParent parent = view.getParent();
StatusBarNotification statusBarNotification =
getRowForParent(parent).getEntry().getSbn();
- final Intent intent = new Intent()
- .setAction(MediaOutputSliceConstants.ACTION_MEDIA_OUTPUT)
- .putExtra(MediaOutputSliceConstants.EXTRA_PACKAGE_NAME,
- statusBarNotification.getPackageName());
- mActivityStarter.startActivity(intent, false, true /* dismissShade */,
- Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ mMediaOutputDialogFactory.create(statusBarNotification.getPackageName(), true);
return true;
}
};
@@ -107,7 +100,7 @@
public MediaTransferManager(Context context) {
mContext = context;
- mActivityStarter = Dependency.get(ActivityStarter.class);
+ mMediaOutputDialogFactory = Dependency.get(MediaOutputDialogFactory.class);
LocalBluetoothManager lbm = Dependency.get(LocalBluetoothManager.class);
InfoMediaManager imm = new InfoMediaManager(mContext, null, null, lbm);
mLocalMediaManager = new LocalMediaManager(mContext, lbm, imm, null);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt
index 433c8b0..ddfa18e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt
@@ -27,10 +27,10 @@
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.NotificationContentView
import com.android.systemui.statusbar.notification.stack.StackStateAnimator
-import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy
import java.util.concurrent.ConcurrentHashMap
import javax.inject.Inject
@@ -85,38 +85,43 @@
for (entry in activeConversationEntries) {
if (rankingMap.getRanking(entry.sbn.key, ranking) && ranking.isConversation) {
val important = ranking.channel.isImportantConversation
- val layouts = entry.row?.layouts?.asSequence()
+ var changed = false
+ entry.row?.layouts?.asSequence()
?.flatMap(::getLayouts)
?.mapNotNull { it as? ConversationLayout }
- ?: emptySequence()
- var changed = false
- for (layout in layouts) {
- if (important == layout.isImportantConversation) {
- continue
- }
- changed = true
- if (important && entry.isMarkedForUserTriggeredMovement) {
- // delay this so that it doesn't animate in until after
- // the notif has been moved in the shade
- mainHandler.postDelayed({
- layout.setIsImportantConversation(
- important, true /* animate */)
- }, IMPORTANCE_ANIMATION_DELAY.toLong())
- } else {
- layout.setIsImportantConversation(important)
- }
- }
+ ?.filterNot { it.isImportantConversation == important }
+ ?.forEach { layout ->
+ changed = true
+ if (important && entry.isMarkedForUserTriggeredMovement) {
+ // delay this so that it doesn't animate in until after
+ // the notif has been moved in the shade
+ mainHandler.postDelayed(
+ {
+ layout.setIsImportantConversation(
+ important,
+ true)
+ },
+ IMPORTANCE_ANIMATION_DELAY.toLong())
+ } else {
+ layout.setIsImportantConversation(important, false)
+ }
+ }
if (changed) {
notificationGroupManager.updateIsolation(entry)
+ // ensure that the conversation icon isn't hidden
+ // (ex: if it was showing in the shelf)
+ entry.row?.updateIconVisibilities()
}
}
}
}
override fun onEntryInflated(entry: NotificationEntry) {
- if (!entry.ranking.isConversation) return
+ if (!entry.ranking.isConversation) {
+ return
+ }
fun updateCount(isExpanded: Boolean) {
- if (isExpanded && (!notifPanelCollapsed || entry.isPinnedAndExpanded())) {
+ if (isExpanded && (!notifPanelCollapsed || entry.isPinnedAndExpanded)) {
resetCount(entry.key)
entry.row?.let(::resetBadgeUi)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 113c115..d8d412b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -1478,8 +1478,9 @@
}
}
- private void updateIconVisibilities() {
- // The shelficon is never hidden for children in groups
+ /** Refreshes the visibility of notification icons */
+ public void updateIconVisibilities() {
+ // The shelf icon is never hidden for children in groups
boolean visible = !isChildInGroup() && mShelfIconVisible;
for (NotificationContentView l : mLayouts) {
l.setShelfIconVisible(visible);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationConversationTemplateViewWrapper.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationConversationTemplateViewWrapper.kt
index fe70c81..17f326b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationConversationTemplateViewWrapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationConversationTemplateViewWrapper.kt
@@ -147,6 +147,8 @@
// hiding the conversationIcon will already do that via its listener.
return
}
+ } else {
+ conversationIconView.isForceHidden = false
}
super.setShelfIconVisible(visible)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartRepliesAndActionsInflater.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartRepliesAndActionsInflater.kt
index b2c1f48..6a3a69c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartRepliesAndActionsInflater.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartRepliesAndActionsInflater.kt
@@ -86,7 +86,7 @@
sysuiContext: Context,
notifPackageContext: Context,
entry: NotificationEntry,
- existingRepliesAndAction: SmartRepliesAndActions
+ existingRepliesAndAction: SmartRepliesAndActions?
): InflatedSmartReplies
}
@@ -103,7 +103,7 @@
sysuiContext: Context,
notifPackageContext: Context,
entry: NotificationEntry,
- existingRepliesAndAction: SmartRepliesAndActions
+ existingRepliesAndAction: SmartRepliesAndActions?
): InflatedSmartReplies {
val newRepliesAndActions = chooseSmartRepliesAndActions(entry)
if (!shouldShowSmartReplyView(entry, newRepliesAndActions)) {
@@ -204,24 +204,26 @@
}
// Apps didn't provide any smart replies / actions, use those from NAS (if any).
if (smartReplies == null && smartActions == null) {
- if (entry.smartReplies.isNotEmpty()
+ val entryReplies = entry.smartReplies
+ val entryActions = entry.smartActions
+ if (entryReplies.isNotEmpty()
&& freeformRemoteInputActionPair != null
&& freeformRemoteInputActionPair.second.allowGeneratedReplies
&& freeformRemoteInputActionPair.second.actionIntent != null) {
smartReplies = SmartReplies(
- entry.smartReplies,
+ entryReplies,
freeformRemoteInputActionPair.first,
freeformRemoteInputActionPair.second.actionIntent,
true /* fromAssistant */)
}
- if (entry.smartActions.isNotEmpty()
+ if (entryActions.isNotEmpty()
&& notification.allowSystemGeneratedContextualActions) {
val systemGeneratedActions: List<Notification.Action> = when {
activityManagerWrapper.isLockTaskKioskModeActive ->
// Filter actions if we're in kiosk-mode - we don't care about screen
// pinning mode, since notifications aren't shown there anyway.
- filterAllowlistedLockTaskApps(entry.smartActions)
- else -> entry.smartActions
+ filterAllowlistedLockTaskApps(entryActions)
+ else -> entryActions
}
smartActions = SmartActions(systemGeneratedActions, true /* fromAssistant */)
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 2081cfe..735338f 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -90,6 +90,7 @@
import com.android.systemui.Dependency;
import com.android.systemui.Prefs;
import com.android.systemui.R;
+import com.android.systemui.media.dialog.MediaOutputDialogFactory;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.VolumeDialog;
import com.android.systemui.plugins.VolumeDialogController;
@@ -519,6 +520,7 @@
Events.writeEvent(Events.EVENT_SETTINGS_CLICK);
Intent intent = new Intent(Settings.Panel.ACTION_VOLUME);
dismissH(DISMISS_REASON_SETTINGS_CLICKED);
+ Dependency.get(MediaOutputDialogFactory.class).dismiss();
Dependency.get(ActivityStarter.class).startActivity(intent,
true /* dismissShade */);
});
diff --git a/packages/SystemUI/tests/AndroidManifest.xml b/packages/SystemUI/tests/AndroidManifest.xml
index db87845..2b4ed4e 100644
--- a/packages/SystemUI/tests/AndroidManifest.xml
+++ b/packages/SystemUI/tests/AndroidManifest.xml
@@ -82,6 +82,10 @@
<activity android:name="com.android.systemui.screenshot.ScrollViewActivity"
android:exported="false" />
+
+ <activity android:name="com.android.systemui.screenshot.RecyclerViewActivity"
+ android:exported="false" />
+
<provider
android:name="androidx.lifecycle.ProcessLifecycleOwnerInitializer"
tools:replace="android:authorities"
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java
index 0a51b26..3c248c7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java
@@ -24,6 +24,7 @@
import static android.view.MotionEvent.ACTION_UP;
import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK;
+import static com.android.systemui.accessibility.MagnificationModeSwitch.FADING_ANIMATION_DURATION_MS;
import static com.android.systemui.accessibility.MagnificationModeSwitch.getIconResId;
import static junit.framework.Assert.assertEquals;
@@ -35,7 +36,6 @@
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -69,6 +69,9 @@
@RunWith(AndroidTestingRunner.class)
public class MagnificationModeSwitchTest extends SysuiTestCase {
+ private static final float FADE_IN_ALPHA = 1f;
+ private static final float FADE_OUT_ALPHA = 0f;
+
private ImageView mSpyImageView;
@Mock
private WindowManager mWindowManager;
@@ -87,49 +90,47 @@
).when(mWindowManager).getMaximumWindowMetrics();
mContext.addMockSystemService(Context.WINDOW_SERVICE, mWindowManager);
mSpyImageView = Mockito.spy(new ImageView(mContext));
- doAnswer(invocation -> null).when(mSpyImageView).setOnTouchListener(
- mTouchListenerCaptor.capture());
- initMockImageViewAndAnimator();
+ resetMockImageViewAndAnimator();
mMagnificationModeSwitch = new MagnificationModeSwitch(mContext, mSpyImageView);
}
@Test
- public void removeButton_removeView() {
+ public void removeButton_buttonIsShowing_removeView() {
mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
mMagnificationModeSwitch.removeButton();
verify(mWindowManager).removeView(mSpyImageView);
- // First invocation is in showButton.
- verify(mViewPropertyAnimator, times(2)).cancel();
+ verify(mViewPropertyAnimator).cancel();
}
@Test
public void showWindowModeButton_fullscreenMode_addViewAndSetImageResource() {
mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
-
- verify(mSpyImageView).setAlpha(1.0f);
verify(mSpyImageView).setImageResource(
getIconResId(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW));
- assertShowButtonAnimation();
+ assertShowFadingAnimation(FADE_IN_ALPHA);
+ assertShowFadingAnimation(FADE_OUT_ALPHA);
+
ArgumentCaptor<Runnable> captor = ArgumentCaptor.forClass(Runnable.class);
verify(mViewPropertyAnimator).withEndAction(captor.capture());
verify(mWindowManager).addView(eq(mSpyImageView), any(WindowManager.LayoutParams.class));
captor.getValue().run();
- // First invocation is in showButton.
- verify(mViewPropertyAnimator, times(2)).cancel();
+ verify(mViewPropertyAnimator).cancel();
verify(mWindowManager).removeView(mSpyImageView);
}
@Test
- public void onConfigurationChanged_setImageResource() {
+ public void onConfigurationChanged_buttonIsShowing_setImageResource() {
mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
+ resetMockImageViewAndAnimator();
+
mMagnificationModeSwitch.onConfigurationChanged(ActivityInfo.CONFIG_DENSITY);
- verify(mSpyImageView, times(2)).setImageResource(
+ verify(mSpyImageView).setImageResource(
getIconResId(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN));
}
@@ -162,7 +163,6 @@
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE, 0);
listener.onTouch(mSpyImageView, MotionEvent.obtain(
0, 0, ACTION_DOWN, 100, 100, 0));
- verify(mSpyImageView).setAlpha(1.0f);
verify(mViewPropertyAnimator).cancel();
listener.onTouch(mSpyImageView, MotionEvent.obtain(
@@ -173,9 +173,8 @@
resetMockImageViewAndAnimator();
listener.onTouch(mSpyImageView, MotionEvent.obtain(
0, ViewConfiguration.getTapTimeout() + 10, ACTION_UP, 100 + offset, 100, 0));
- verify(mSpyImageView).setAlpha(1.0f);
assertModeUnchanged(previousMode);
- assertShowButtonAnimation();
+ assertShowFadingAnimation(FADE_OUT_ALPHA);
}
@Test
@@ -193,9 +192,8 @@
resetMockImageViewAndAnimator();
listener.onTouch(mSpyImageView, MotionEvent.obtain(
0, ViewConfiguration.getTapTimeout(), ACTION_CANCEL, 100, 100, 0));
- verify(mSpyImageView).setAlpha(1.0f);
assertModeUnchanged(previousMode);
- assertShowButtonAnimation();
+ assertShowFadingAnimation(FADE_OUT_ALPHA);
}
@Test
@@ -216,9 +214,8 @@
resetMockImageViewAndAnimator();
listener.onTouch(mSpyImageView, MotionEvent.obtain(
0, ViewConfiguration.getTapTimeout(), ACTION_CANCEL, 100 + offset, 100, 0));
- verify(mSpyImageView).setAlpha(1.0f);
assertModeUnchanged(previousMode);
- assertShowButtonAnimation();
+ assertShowFadingAnimation(FADE_OUT_ALPHA);
}
@Test
@@ -249,37 +246,55 @@
verifyTapAction(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
}
+ @Test
+ public void showButton_showFadeOutAnimation_fadeOutAnimationCanceled() {
+ mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
+ assertShowFadingAnimation(FADE_OUT_ALPHA);
+ resetMockImageViewAndAnimator();
+
+ mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
+
+ verify(mViewPropertyAnimator).cancel();
+ assertEquals(1f, mSpyImageView.getAlpha());
+ assertShowFadingAnimation(FADE_OUT_ALPHA);
+ }
+
private void assertModeUnchanged(int expectedMode) {
final int actualMode = Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE, 0);
assertEquals(expectedMode, actualMode);
}
- private void assertShowButtonAnimation() {
- verify(mViewPropertyAnimator).cancel();
- verify(mViewPropertyAnimator).setDuration(anyLong());
- verify(mViewPropertyAnimator).alpha(anyFloat());
+ private void assertShowFadingAnimation(float alpha) {
+ ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class);
+ if (alpha == FADE_IN_ALPHA) { // Fade-in
+ verify(mSpyImageView).postOnAnimation(runnableCaptor.capture());
+ } else { // Fade-out
+ verify(mSpyImageView).postOnAnimationDelayed(runnableCaptor.capture(), anyLong());
+ }
+ resetMockAnimator();
+
+ runnableCaptor.getValue().run();
+
+ verify(mViewPropertyAnimator).setDuration(eq(FADING_ANIMATION_DURATION_MS));
+ verify(mViewPropertyAnimator).alpha(alpha);
verify(mViewPropertyAnimator).start();
}
- private void initMockImageViewAndAnimator() {
+ private void resetMockImageViewAndAnimator() {
+ Mockito.reset(mSpyImageView);
+ doAnswer(invocation -> null).when(mSpyImageView).setOnTouchListener(
+ mTouchListenerCaptor.capture());
+ resetMockAnimator();
+ }
+
+ private void resetMockAnimator() {
+ Mockito.reset(mViewPropertyAnimator);
when(mViewPropertyAnimator.setDuration(anyLong())).thenReturn(mViewPropertyAnimator);
when(mViewPropertyAnimator.alpha(anyFloat())).thenReturn(mViewPropertyAnimator);
when(mViewPropertyAnimator.withEndAction(any(Runnable.class))).thenReturn(
mViewPropertyAnimator);
-
when(mSpyImageView.animate()).thenReturn(mViewPropertyAnimator);
- doAnswer(invocation -> {
- Runnable run = invocation.getArgument(0);
- run.run();
- return null;
- }).when(mSpyImageView).postDelayed(any(), anyLong());
- }
-
- private void resetMockImageViewAndAnimator() {
- Mockito.reset(mViewPropertyAnimator);
- Mockito.reset(mSpyImageView);
- initMockImageViewAndAnimator();
}
/**
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
index 99e39b8..e24f4ca3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
@@ -222,7 +222,7 @@
mTouchListenerCaptor.getValue().onTouch(mUdfpsView, event);
event.recycle();
// THEN the event is passed to the FingerprintManager
- verify(mFingerprintManager).onFingerDown(eq(mUdfpsController.mUdfpsSensorId), eq(0), eq(0),
+ verify(mFingerprintManager).onPointerDown(eq(mUdfpsController.mUdfpsSensorId), eq(0), eq(0),
eq(0f), eq(0f));
// AND the scrim and dot is shown
verify(mUdfpsView).showScrimAndDot();
@@ -236,7 +236,7 @@
// WHEN fingerprint is requested because of AOD interrupt
mUdfpsController.onAodInterrupt(0, 0);
// THEN the event is passed to the FingerprintManager
- verify(mFingerprintManager).onFingerDown(eq(mUdfpsController.mUdfpsSensorId), eq(0), eq(0),
+ verify(mFingerprintManager).onPointerDown(eq(mUdfpsController.mUdfpsSensorId), eq(0), eq(0),
anyFloat(), anyFloat());
// AND the scrim and dot is shown
verify(mUdfpsView).showScrimAndDot();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt
index 81139f19..182a056 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt
@@ -38,6 +38,7 @@
import androidx.lifecycle.LiveData
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
+import com.android.systemui.media.dialog.MediaOutputDialogFactory
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.statusbar.phone.KeyguardDismissUtil
import com.android.systemui.util.animation.TransitionLayout
@@ -92,6 +93,7 @@
@Mock private lateinit var mediaDataManager: MediaDataManager
@Mock private lateinit var expandedSet: ConstraintSet
@Mock private lateinit var collapsedSet: ConstraintSet
+ @Mock private lateinit var mediaOutputDialogFactory: MediaOutputDialogFactory
private lateinit var appIcon: ImageView
private lateinit var appName: TextView
private lateinit var albumView: ImageView
@@ -126,7 +128,8 @@
whenever(mediaViewController.collapsedLayout).thenReturn(collapsedSet)
player = MediaControlPanel(context, bgExecutor, activityStarter, mediaViewController,
- seekBarViewModel, Lazy { mediaDataManager }, keyguardDismissUtil)
+ seekBarViewModel, Lazy { mediaDataManager }, keyguardDismissUtil,
+ mediaOutputDialogFactory)
whenever(seekBarViewModel.progress).thenReturn(seekBarData)
// Mock out a view holder for the player to attach to.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/RecyclerViewActivity.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/RecyclerViewActivity.java
new file mode 100644
index 0000000..fde56ba
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/RecyclerViewActivity.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.screenshot;
+
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+
+import android.app.Activity;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import androidx.annotation.Nullable;
+
+import com.android.internal.widget.LinearLayoutManager;
+import com.android.internal.widget.RecyclerView;
+import com.android.internal.widget.RecyclerView.LayoutParams;
+
+import java.util.Random;
+
+public class RecyclerViewActivity extends Activity {
+ public static final int CHILD_VIEW_HEIGHT = 300;
+ private static final int CHILD_VIEWS = 12;
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ RecyclerView recyclerView = new RecyclerView(this);
+ recyclerView.setLayoutManager(new LinearLayoutManager(this));
+ recyclerView.setAdapter(new TestAdapter());
+ recyclerView.setLayoutParams(new LayoutParams(MATCH_PARENT, MATCH_PARENT));
+ setContentView(recyclerView);
+ }
+
+ static final class TestViewHolder extends RecyclerView.ViewHolder {
+ TestViewHolder(View itemView) {
+ super(itemView);
+ }
+ }
+
+ static final class TestAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
+ private final Random mRandom = new Random();
+
+ @Override
+ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ return new TestViewHolder(new TextView(parent.getContext()));
+ }
+
+ @Override
+ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
+ TextView view = (TextView) holder.itemView;
+ view.setText("Child #" + position);
+ view.setTextColor(Color.WHITE);
+ view.setTextSize(30f);
+ view.setBackgroundColor(
+ Color.rgb(mRandom.nextFloat(), mRandom.nextFloat(), mRandom.nextFloat()));
+ view.setMinHeight(CHILD_VIEW_HEIGHT);
+ }
+
+ @Override
+ public int getItemCount() {
+ return CHILD_VIEWS;
+ }
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
index 3e1616c..d04d8ee 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
@@ -21,6 +21,8 @@
import static com.android.systemui.statusbar.notification.NotificationEntryManager.UNDEFINED_DISMISS_REASON;
+import static com.google.common.truth.Truth.assertThat;
+
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
@@ -346,7 +348,7 @@
setSmartActions(mEntry.getKey(), null);
mEntryManager.updateNotificationRanking(mRankingMap);
- assertNull(mEntry.getSmartActions());
+ assertThat(mEntry.getSmartActions()).isEmpty();
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/InflatedSmartRepliesTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/InflatedSmartRepliesTest.java
index e93c5db..8ee15bb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/InflatedSmartRepliesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/InflatedSmartRepliesTest.java
@@ -183,8 +183,7 @@
SmartRepliesAndActions repliesAndActions =
mSmartRepliesInflater.chooseSmartRepliesAndActions(mEntry);
- assertThat(repliesAndActions.smartReplies.choices).isEqualTo(
- mEntry.getSmartReplies());
+ assertThat(repliesAndActions.smartReplies.choices).isEqualTo(mEntry.getSmartReplies());
assertThat(repliesAndActions.smartReplies.fromAssistant).isTrue();
assertThat(repliesAndActions.smartActions).isNull();
}
diff --git a/packages/Tethering/tests/privileged/src/android/net/ip/DadProxyTest.java b/packages/Tethering/tests/privileged/src/android/net/ip/DadProxyTest.java
index 747d3e8..95e36fa 100644
--- a/packages/Tethering/tests/privileged/src/android/net/ip/DadProxyTest.java
+++ b/packages/Tethering/tests/privileged/src/android/net/ip/DadProxyTest.java
@@ -33,7 +33,6 @@
import android.net.TestNetworkInterface;
import android.net.TestNetworkManager;
import android.net.util.InterfaceParams;
-import android.net.util.IpUtils;
import android.net.util.TetheringUtils;
import android.os.Handler;
import android.os.HandlerThread;
@@ -46,6 +45,7 @@
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.net.module.util.IpUtils;
import com.android.testutils.TapPacketReader;
import org.junit.After;
diff --git a/services/Android.bp b/services/Android.bp
index a689236..33205c0 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -35,6 +35,7 @@
":services.coverage-sources",
":services.devicepolicy-sources",
":services.midi-sources",
+ ":services.musicsearch-sources",
":services.net-sources",
":services.print-sources",
":services.profcollect-sources",
@@ -78,6 +79,7 @@
"services.coverage",
"services.devicepolicy",
"services.midi",
+ "services.musicsearch",
"services.net",
"services.people",
"services.print",
diff --git a/services/core/Android.bp b/services/core/Android.bp
index addaa65..26c28d5 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -109,6 +109,7 @@
"android.hardware.weaver-V1.0-java",
"android.hardware.biometrics.face-V1.1-java",
"android.hardware.biometrics.fingerprint-V2.3-java",
+ "android.hardware.biometrics.fingerprint-java",
"android.hardware.oemlock-V1.0-java",
"android.hardware.configstore-V1.0-java",
"android.hardware.contexthub-V1.0-java",
diff --git a/services/core/java/com/android/server/MountServiceIdler.java b/services/core/java/com/android/server/MountServiceIdler.java
index 6bc1a57..0f4c94b 100644
--- a/services/core/java/com/android/server/MountServiceIdler.java
+++ b/services/core/java/com/android/server/MountServiceIdler.java
@@ -113,6 +113,7 @@
JobInfo.Builder builder = new JobInfo.Builder(MOUNT_JOB_ID, sIdleService);
builder.setRequiresDeviceIdle(true);
builder.setRequiresBatteryNotLow(true);
+ builder.setRequiresCharging(true);
builder.setMinimumLatency(nextScheduleTime);
tm.schedule(builder.build());
}
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index b6a3e23..8ea71b3 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -1623,10 +1623,12 @@
if (!checkNotifyPermission("notifyDisplayInfoChanged()")) {
return;
}
+ String str = "notifyDisplayInfoChanged: PhoneId=" + phoneId + " subId=" + subId
+ + " telephonyDisplayInfo=" + telephonyDisplayInfo;
if (VDBG) {
- log("notifyDisplayInfoChanged: PhoneId=" + phoneId
- + " subId=" + subId + " telephonyDisplayInfo=" + telephonyDisplayInfo);
+ log(str);
}
+ mLocalLog.log(str);
synchronized (mRecords) {
if (validatePhoneId(phoneId)) {
mTelephonyDisplayInfos[phoneId] = telephonyDisplayInfo;
@@ -2354,10 +2356,10 @@
pw.println("mOutgoingCallEmergencyNumber=" + mOutgoingCallEmergencyNumber[i]);
pw.println("mOutgoingSmsEmergencyNumber=" + mOutgoingSmsEmergencyNumber[i]);
pw.println("mBarringInfo=" + mBarringInfo.get(i));
+ pw.println("mTelephonyDisplayInfo=" + mTelephonyDisplayInfos[i]);
pw.decreaseIndent();
}
pw.println("mCarrierNetworkChangeState=" + mCarrierNetworkChangeState);
-
pw.println("mPhoneCapability=" + mPhoneCapability);
pw.println("mActiveDataSubId=" + mActiveDataSubId);
pw.println("mRadioPowerState=" + mRadioPowerState);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 4e9d456..9afda8c 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -12127,6 +12127,7 @@
app.setHasClientActivities(false);
mServices.killServicesLocked(app, allowRestart);
+ mPhantomProcessList.onAppDied(app.pid);
boolean restart = false;
@@ -15789,6 +15790,11 @@
}
@Override
+ public int getPendingIntentFlags(IIntentSender target) {
+ return mPendingIntentController.getPendingIntentFlags(target);
+ }
+
+ @Override
public void setPendingIntentAllowBgActivityStarts(IIntentSender target,
IBinder whitelistToken, int flags) {
if (!(target instanceof PendingIntentRecord)) {
diff --git a/services/core/java/com/android/server/am/PendingIntentController.java b/services/core/java/com/android/server/am/PendingIntentController.java
index c62df56..2ae3d35 100644
--- a/services/core/java/com/android/server/am/PendingIntentController.java
+++ b/services/core/java/com/android/server/am/PendingIntentController.java
@@ -311,6 +311,16 @@
}
}
+ int getPendingIntentFlags(IIntentSender target) {
+ if (!(target instanceof PendingIntentRecord)) {
+ Slog.w(TAG, "markAsSentFromNotification(): not a PendingIntentRecord: " + target);
+ return 0;
+ }
+ synchronized (mLock) {
+ return ((PendingIntentRecord) target).key.flags;
+ }
+ }
+
private void makeIntentSenderCanceled(PendingIntentRecord rec) {
rec.canceled = true;
final RemoteCallbackList<IResultReceiver> callbacks = rec.detachCancelListenersLocked();
diff --git a/services/core/java/com/android/server/am/PhantomProcessList.java b/services/core/java/com/android/server/am/PhantomProcessList.java
index e2fcf08..5167c57 100644
--- a/services/core/java/com/android/server/am/PhantomProcessList.java
+++ b/services/core/java/com/android/server/am/PhantomProcessList.java
@@ -27,15 +27,22 @@
import android.app.ApplicationExitInfo.SubReason;
import android.os.Handler;
import android.os.Process;
+import android.os.StrictMode;
import android.util.Slog;
import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.ProcStatsUtil;
import com.android.internal.os.ProcessCpuTracker;
import libcore.io.IoUtils;
import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
@@ -78,18 +85,178 @@
@GuardedBy("mLock")
private final ArrayList<PhantomProcessRecord> mTempPhantomProcesses = new ArrayList<>();
+ /**
+ * The mapping between a phantom process ID to its parent process (an app process)
+ */
+ @GuardedBy("mLock")
+ private final SparseArray<ProcessRecord> mPhantomToAppProcessMap = new SparseArray<>();
+
+ @GuardedBy("mLock")
+ private final SparseArray<InputStream> mCgroupProcsFds = new SparseArray<>();
+
+ @GuardedBy("mLock")
+ private final byte[] mDataBuffer = new byte[4096];
+
@GuardedBy("mLock")
private boolean mTrimPhantomProcessScheduled = false;
@GuardedBy("mLock")
int mUpdateSeq;
+ @VisibleForTesting
+ Injector mInjector;
+
private final ActivityManagerService mService;
private final Handler mKillHandler;
PhantomProcessList(final ActivityManagerService service) {
mService = service;
mKillHandler = service.mProcessList.sKillHandler;
+ mInjector = new Injector();
+ }
+
+ @VisibleForTesting
+ @GuardedBy("mLock")
+ void lookForPhantomProcessesLocked() {
+ mPhantomToAppProcessMap.clear();
+ StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
+ try {
+ synchronized (mService.mPidsSelfLocked) {
+ for (int i = mService.mPidsSelfLocked.size() - 1; i >= 0; i--) {
+ final ProcessRecord app = mService.mPidsSelfLocked.valueAt(i);
+ lookForPhantomProcessesLocked(app);
+ }
+ }
+ } finally {
+ StrictMode.setThreadPolicy(oldPolicy);
+ }
+ }
+
+ @GuardedBy({"mLock", "mService.mPidsSelfLocked"})
+ private void lookForPhantomProcessesLocked(ProcessRecord app) {
+ if (app.appZygote || app.killed || app.killedByAm) {
+ // process forked from app zygote doesn't have its own acct entry
+ return;
+ }
+ InputStream input = mCgroupProcsFds.get(app.pid);
+ if (input == null) {
+ final String path = getCgroupFilePath(app.info.uid, app.pid);
+ try {
+ input = mInjector.openCgroupProcs(path);
+ } catch (FileNotFoundException | SecurityException e) {
+ if (DEBUG_PROCESSES) {
+ Slog.w(TAG, "Unable to open " + path, e);
+ }
+ return;
+ }
+ // Keep the FD open for better performance
+ mCgroupProcsFds.put(app.pid, input);
+ }
+ final byte[] buf = mDataBuffer;
+ try {
+ int read = 0;
+ int pid = 0;
+ long totalRead = 0;
+ do {
+ read = mInjector.readCgroupProcs(input, buf, 0, buf.length);
+ if (read == -1) {
+ break;
+ }
+ totalRead += read;
+ for (int i = 0; i < read; i++) {
+ final byte b = buf[i];
+ if (b == '\n') {
+ addChildPidLocked(app, pid);
+ pid = 0;
+ } else {
+ pid = pid * 10 + (b - '0');
+ }
+ }
+ if (read < buf.length) {
+ // we may break from here safely as sysfs reading should return the whole page
+ // if the remaining data is larger than a page
+ break;
+ }
+ } while (true);
+ if (pid != 0) {
+ addChildPidLocked(app, pid);
+ }
+ // rewind the fd for the next read
+ input.skip(-totalRead);
+ } catch (IOException e) {
+ Slog.e(TAG, "Error in reading cgroup procs from " + app, e);
+ IoUtils.closeQuietly(input);
+ mCgroupProcsFds.delete(app.pid);
+ }
+ }
+
+ @VisibleForTesting
+ static String getCgroupFilePath(int uid, int pid) {
+ return "/acct/uid_" + uid + "/pid_" + pid + "/cgroup.procs";
+ }
+
+ static String getProcessName(int pid) {
+ String procName = ProcStatsUtil.readTerminatedProcFile(
+ "/proc/" + pid + "/cmdline", (byte) '\0');
+ if (procName == null) {
+ return null;
+ }
+ int l = procName.lastIndexOf('/');
+ if (l > 0 && l < procName.length() - 1) {
+ procName = procName.substring(l + 1);
+ }
+ return procName;
+ }
+
+ @GuardedBy({"mLock", "mService.mPidsSelfLocked"})
+ private void addChildPidLocked(final ProcessRecord app, final int pid) {
+ if (app.pid != pid) {
+ // That's something else...
+ final ProcessRecord r = mService.mPidsSelfLocked.get(pid);
+ if (r != null) {
+ // Is this a process forked via app zygote?
+ if (!r.appZygote) {
+ // Unexpected...
+ if (DEBUG_PROCESSES) {
+ Slog.w(TAG, "Unexpected: " + r + " appears in the cgroup.procs of " + app);
+ }
+ } else {
+ // Just a child process of app zygote, no worries
+ }
+ } else {
+ final int index = mPhantomToAppProcessMap.indexOfKey(pid);
+ if (index >= 0) { // unlikely since we cleared the map at the beginning
+ final ProcessRecord current = mPhantomToAppProcessMap.valueAt(index);
+ if (app == current) {
+ // Okay it's unchanged
+ return;
+ }
+ mPhantomToAppProcessMap.setValueAt(index, app);
+ } else {
+ mPhantomToAppProcessMap.put(pid, app);
+ }
+ // Its UID isn't necessarily to be the same as the app.info.uid, since it could be
+ // forked from child processes of app zygote
+ final int uid = Process.getUidForPid(pid);
+ String procName = mInjector.getProcessName(pid);
+ if (procName == null || uid < 0) {
+ mPhantomToAppProcessMap.delete(pid);
+ return;
+ }
+ getOrCreatePhantomProcessIfNeededLocked(procName, uid, pid, true);
+ }
+ }
+ }
+
+ void onAppDied(final int pid) {
+ synchronized (mLock) {
+ final int index = mCgroupProcsFds.indexOfKey(pid);
+ if (index >= 0) {
+ final InputStream inputStream = mCgroupProcsFds.valueAt(index);
+ mCgroupProcsFds.removeAt(index);
+ IoUtils.closeQuietly(inputStream);
+ }
+ }
}
/**
@@ -99,7 +266,7 @@
*/
@GuardedBy("mLock")
PhantomProcessRecord getOrCreatePhantomProcessIfNeededLocked(final String processName,
- final int uid, final int pid) {
+ final int uid, final int pid, boolean createIfNeeded) {
// First check if it's actually an app process we know
if (isAppProcess(pid)) {
return null;
@@ -123,56 +290,47 @@
if (proc.equals(processName, uid, pid)) {
return proc;
}
- // Our zombie process information is outdated, let's remove this one, it shoud
+ // Our zombie process information is outdated, let's remove this one, it should
// have been gone.
mZombiePhantomProcesses.removeAt(idx);
}
}
- int ppid = getParentPid(pid);
+ if (!createIfNeeded) {
+ return null;
+ }
- // Walk through its parents and see if it could be traced back to an app process.
- while (ppid > 1) {
- if (isAppProcess(ppid)) {
- // It's a phantom process, bookkeep it
- try {
- final PhantomProcessRecord proc = new PhantomProcessRecord(
- processName, uid, pid, ppid, mService,
- this::onPhantomProcessKilledLocked);
- proc.mUpdateSeq = mUpdateSeq;
- mPhantomProcesses.put(pid, proc);
- SparseArray<PhantomProcessRecord> array = mAppPhantomProcessMap.get(ppid);
- if (array == null) {
- array = new SparseArray<>();
- mAppPhantomProcessMap.put(ppid, array);
- }
- array.put(pid, proc);
- if (proc.mPidFd != null) {
- mKillHandler.getLooper().getQueue().addOnFileDescriptorEventListener(
- proc.mPidFd, EVENT_INPUT | EVENT_ERROR,
- this::onPhantomProcessFdEvent);
- mPhantomProcessesPidFds.put(proc.mPidFd.getInt$(), proc);
- }
- scheduleTrimPhantomProcessesLocked();
- return proc;
- } catch (IllegalStateException e) {
- return null;
+ final ProcessRecord r = mPhantomToAppProcessMap.get(pid);
+
+ if (r != null) {
+ // It's a phantom process, bookkeep it
+ try {
+ final PhantomProcessRecord proc = new PhantomProcessRecord(
+ processName, uid, pid, r.pid, mService,
+ this::onPhantomProcessKilledLocked);
+ proc.mUpdateSeq = mUpdateSeq;
+ mPhantomProcesses.put(pid, proc);
+ SparseArray<PhantomProcessRecord> array = mAppPhantomProcessMap.get(r.pid);
+ if (array == null) {
+ array = new SparseArray<>();
+ mAppPhantomProcessMap.put(r.pid, array);
}
+ array.put(pid, proc);
+ if (proc.mPidFd != null) {
+ mKillHandler.getLooper().getQueue().addOnFileDescriptorEventListener(
+ proc.mPidFd, EVENT_INPUT | EVENT_ERROR,
+ this::onPhantomProcessFdEvent);
+ mPhantomProcessesPidFds.put(proc.mPidFd.getInt$(), proc);
+ }
+ scheduleTrimPhantomProcessesLocked();
+ return proc;
+ } catch (IllegalStateException e) {
+ return null;
}
-
- ppid = getParentPid(ppid);
}
return null;
}
- private static int getParentPid(int pid) {
- try {
- return Process.getParentPid(pid);
- } catch (Exception e) {
- }
- return -1;
- }
-
private boolean isAppProcess(int pid) {
synchronized (mService.mPidsSelfLocked) {
return mService.mPidsSelfLocked.get(pid) != null;
@@ -346,10 +504,14 @@
synchronized (mLock) {
// refresh the phantom process list with the latest cpu stats results.
mUpdateSeq++;
+
+ // Scan app process's accounting procs
+ lookForPhantomProcessesLocked();
+
for (int i = tracker.countStats() - 1; i >= 0; i--) {
final ProcessCpuTracker.Stats st = tracker.getStats(i);
final PhantomProcessRecord r =
- getOrCreatePhantomProcessIfNeededLocked(st.name, st.uid, st.pid);
+ getOrCreatePhantomProcessIfNeededLocked(st.name, st.uid, st.pid, false);
if (r != null) {
r.mUpdateSeq = mUpdateSeq;
r.mCurrentCputime += st.rel_utime + st.rel_stime;
@@ -392,4 +554,19 @@
proc.dump(pw, prefix + " ");
}
}
+
+ @VisibleForTesting
+ static class Injector {
+ InputStream openCgroupProcs(String path) throws FileNotFoundException, SecurityException {
+ return new FileInputStream(path);
+ }
+
+ int readCgroupProcs(InputStream input, byte[] buf, int offset, int len) throws IOException {
+ return input.read(buf, offset, len);
+ }
+
+ String getProcessName(final int pid) {
+ return PhantomProcessList.getProcessName(pid);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index bad03c1..cf0223b 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -2540,8 +2540,8 @@
app.hostingRecord.getName() != null ? app.hostingRecord.getName() : "");
try {
- AppGlobals.getPackageManager().logAppProcessStartIfNeeded(app.processName, app.uid,
- app.seInfo, app.info.sourceDir, pid);
+ AppGlobals.getPackageManager().logAppProcessStartIfNeeded(app.info.packageName,
+ app.processName, app.uid, app.seInfo, app.info.sourceDir, pid);
} catch (RemoteException ex) {
// Ignore
}
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index 1615998..3b407f1 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -25,6 +25,8 @@
import android.content.Context;
import android.content.Intent;
import android.media.AudioDeviceAttributes;
+import android.media.AudioDeviceInfo;
+import android.media.AudioManager;
import android.media.AudioRoutesInfo;
import android.media.AudioSystem;
import android.media.IAudioRoutesObserver;
@@ -39,6 +41,7 @@
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.SystemClock;
+import android.os.UserHandle;
import android.text.TextUtils;
import android.util.Log;
import android.util.PrintWriterPrinter;
@@ -46,8 +49,8 @@
import com.android.internal.annotations.GuardedBy;
import java.io.PrintWriter;
-import java.util.ArrayList;
import java.util.HashSet;
+import java.util.LinkedList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Set;
@@ -73,10 +76,6 @@
/** Forced device usage for communications sent to AudioSystem */
private int mForcedUseForComm;
- /**
- * Externally reported force device usage state returned by getters: always consistent
- * with requests by setters */
- private int mForcedUseForCommExt;
// Manages all connected devices, only ever accessed on the message loop
private final AudioDeviceInventory mDeviceInventory;
@@ -136,7 +135,6 @@
setupMessaging(mContext);
mForcedUseForComm = AudioSystem.FORCE_NONE;
- mForcedUseForCommExt = mForcedUseForComm;
}
/*package*/ Context getContext() {
@@ -159,15 +157,6 @@
}
/*package*/ void onAudioServerDied() {
- // Restore forced usage for communications and record
- synchronized (mDeviceStateLock) {
- AudioSystem.setParameters(
- "BT_SCO=" + (mForcedUseForComm == AudioSystem.FORCE_BT_SCO ? "on" : "off"));
- onSetForceUse(AudioSystem.FOR_COMMUNICATION, mForcedUseForComm,
- false /*fromA2dp*/, "onAudioServerDied");
- onSetForceUse(AudioSystem.FOR_RECORD, mForcedUseForComm,
- false /*fromA2dp*/, "onAudioServerDied");
- }
// restore devices
sendMsgNoDelay(MSG_RESTORE_DEVICES, SENDMSG_REPLACE);
}
@@ -219,85 +208,156 @@
* Turns speakerphone on/off
* @param on
* @param eventSource for logging purposes
- * @return true if speakerphone state changed
*/
- /*package*/ boolean setSpeakerphoneOn(IBinder cb, int pid, boolean on, String eventSource) {
- synchronized (mDeviceStateLock) {
- if (!addSpeakerphoneClient(cb, pid, on)) {
- return false;
+ /*package*/ void setSpeakerphoneOn(IBinder cb, int pid, boolean on, String eventSource) {
+
+ if (AudioService.DEBUG_COMM_RTE) {
+ Log.v(TAG, "setSpeakerphoneOn, on: " + on + " pid: " + pid);
+ }
+
+ synchronized (mSetModeLock) {
+ synchronized (mDeviceStateLock) {
+ AudioDeviceAttributes device = null;
+ if (on) {
+ device = new AudioDeviceAttributes(AudioDeviceAttributes.ROLE_OUTPUT,
+ AudioDeviceInfo.TYPE_BUILTIN_SPEAKER, "");
+ } else {
+ CommunicationRouteClient client = getCommunicationRouteClientForPid(pid);
+ if (client == null || !client.requestsSpeakerphone()) {
+ return;
+ }
+ }
+ setCommunicationRouteForClient(
+ cb, pid, device, BtHelper.SCO_MODE_UNDEFINED, eventSource);
}
- if (on) {
- // Cancel BT SCO ON request by this same client: speakerphone and BT SCO routes
- // are mutually exclusive.
- // See symmetrical operation for startBluetoothScoForClient_Sync().
- mBtHelper.stopBluetoothScoForPid(pid);
- }
- final boolean wasOn = isSpeakerphoneOn();
- updateSpeakerphoneOn(eventSource);
- return (wasOn != isSpeakerphoneOn());
}
}
- /**
- * Turns speakerphone off for a given pid and update speakerphone state.
- * @param pid
- */
@GuardedBy("mDeviceStateLock")
- private void setSpeakerphoneOffForPid(int pid) {
- SpeakerphoneClient client = getSpeakerphoneClientForPid(pid);
+ /*package*/ void setCommunicationRouteForClient(
+ IBinder cb, int pid, AudioDeviceAttributes device,
+ int scoAudioMode, String eventSource) {
+
+ if (AudioService.DEBUG_COMM_RTE) {
+ Log.v(TAG, "setCommunicationRouteForClient: device: " + device);
+ }
+
+ final boolean wasBtScoRequested = isBluetoothScoRequested();
+ final boolean wasSpeakerphoneRequested = isSpeakerphoneRequested();
+ CommunicationRouteClient client;
+
+
+ // Save previous client route in case of failure to start BT SCO audio
+ AudioDeviceAttributes prevClientDevice = null;
+ client = getCommunicationRouteClientForPid(pid);
+ if (client != null) {
+ prevClientDevice = client.getDevice();
+ }
+
+ if (device != null) {
+ client = addCommunicationRouteClient(cb, pid, device);
+ if (client == null) {
+ Log.w(TAG, "setCommunicationRouteForClient: could not add client for pid: "
+ + pid + " and device: " + device);
+ }
+ } else {
+ client = removeCommunicationRouteClient(cb, true);
+ }
if (client == null) {
return;
}
- client.unregisterDeathRecipient();
- mSpeakerphoneClients.remove(client);
- final String eventSource = new StringBuilder("setSpeakerphoneOffForPid(")
- .append(pid).append(")").toString();
- updateSpeakerphoneOn(eventSource);
- }
- @GuardedBy("mDeviceStateLock")
- private void updateSpeakerphoneOn(String eventSource) {
- if (isSpeakerphoneOnRequested()) {
- if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) {
- setForceUse_Async(AudioSystem.FOR_RECORD, AudioSystem.FORCE_NONE, eventSource);
+ boolean isBtScoRequested = isBluetoothScoRequested();
+ if (isBtScoRequested && !wasBtScoRequested) {
+ if (!mBtHelper.startBluetoothSco(scoAudioMode, eventSource)) {
+ Log.w(TAG, "setCommunicationRouteForClient: failure to start BT SCO for pid: "
+ + pid);
+ // clean up or restore previous client selection
+ if (prevClientDevice != null) {
+ addCommunicationRouteClient(cb, pid, prevClientDevice);
+ } else {
+ removeCommunicationRouteClient(cb, true);
+ }
}
- mForcedUseForComm = AudioSystem.FORCE_SPEAKER;
- } else if (mForcedUseForComm == AudioSystem.FORCE_SPEAKER) {
- if (mBtHelper.isBluetoothScoOn()) {
- mForcedUseForComm = AudioSystem.FORCE_BT_SCO;
- setForceUse_Async(
- AudioSystem.FOR_RECORD, AudioSystem.FORCE_BT_SCO, eventSource);
- } else {
- mForcedUseForComm = AudioSystem.FORCE_NONE;
+ } else if (!isBtScoRequested && wasBtScoRequested) {
+ mBtHelper.stopBluetoothSco(eventSource);
+ }
+
+ if (wasSpeakerphoneRequested != isSpeakerphoneRequested()) {
+ try {
+ mContext.sendBroadcastAsUser(
+ new Intent(AudioManager.ACTION_SPEAKERPHONE_STATE_CHANGED)
+ .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY), UserHandle.ALL);
+ } catch (Exception e) {
+ Log.w(TAG, "failed to broadcast ACTION_SPEAKERPHONE_STATE_CHANGED: " + e);
}
}
- mForcedUseForCommExt = mForcedUseForComm;
- setForceUse_Async(AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, eventSource);
+
+ sendLMsgNoDelay(MSG_L_UPDATE_COMMUNICATION_ROUTE, SENDMSG_QUEUE, eventSource);
}
/**
- * Returns if speakerphone is requested ON or OFF.
- * If the current audio mode owner is in the speakerphone client list, use this preference.
+ * Returns the device currently requested for communication use case.
+ * If the current audio mode owner is in the communication route client list,
+ * use this preference.
* Otherwise use first client's preference (first client corresponds to latest request).
- * Speakerphone is requested OFF if no client is in the list.
- * @return true if speakerphone is requested ON, false otherwise
+ * null is returned if no client is in the list.
+ * @return AudioDeviceAttributes the requested device for communication.
*/
+
@GuardedBy("mDeviceStateLock")
- private boolean isSpeakerphoneOnRequested() {
- if (mSpeakerphoneClients.isEmpty()) {
- return false;
- }
- for (SpeakerphoneClient cl : mSpeakerphoneClients) {
+ private AudioDeviceAttributes requestedCommunicationDevice() {
+ AudioDeviceAttributes device = null;
+ for (CommunicationRouteClient cl : mCommunicationRouteClients) {
if (cl.getPid() == mModeOwnerPid) {
- return cl.isOn();
+ device = cl.getDevice();
}
}
- return mSpeakerphoneClients.get(0).isOn();
+ if (!mCommunicationRouteClients.isEmpty() && mModeOwnerPid == 0) {
+ device = mCommunicationRouteClients.get(0).getDevice();
+ }
+
+ if (AudioService.DEBUG_COMM_RTE) {
+ Log.v(TAG, "requestedCommunicationDevice, device: "
+ + device + " mode owner pid: " + mModeOwnerPid);
+ }
+ return device;
}
- /*package*/ boolean isSpeakerphoneOn() {
+ /**
+ * Helper method on top of requestedCommunicationDevice() indicating if
+ * speakerphone ON is currently requested or not.
+ * @return true if speakerphone ON requested, false otherwise.
+ */
+
+ private boolean isSpeakerphoneRequested() {
synchronized (mDeviceStateLock) {
- return (mForcedUseForCommExt == AudioSystem.FORCE_SPEAKER);
+ AudioDeviceAttributes device = requestedCommunicationDevice();
+ return device != null
+ && device.getType()
+ == AudioDeviceInfo.TYPE_BUILTIN_SPEAKER;
+ }
+ }
+
+ /**
+ * Indicates if active route selection for communication is speakerphone.
+ * @return true if speakerphone is active, false otherwise.
+ */
+ /*package*/ boolean isSpeakerphoneOn() {
+ return getForcedUseForComm() == AudioSystem.FORCE_SPEAKER;
+ }
+
+ /**
+ * Helper method on top of requestedCommunicationDevice() indicating if
+ * Bluetooth SCO ON is currently requested or not.
+ * @return true if Bluetooth SCO ON is requested, false otherwise.
+ */
+ /*package*/ boolean isBluetoothScoRequested() {
+ synchronized (mDeviceStateLock) {
+ AudioDeviceAttributes device = requestedCommunicationDevice();
+ return device != null
+ && device.getType()
+ == AudioDeviceInfo.TYPE_BLUETOOTH_SCO;
}
}
@@ -348,7 +408,6 @@
}
}
-
/*package*/ void postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
@NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state,
int profile, boolean suppressNoisyIntent, int a2dpVolume) {
@@ -431,42 +490,28 @@
sendLMsgNoDelay(MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT, SENDMSG_QUEUE, info);
}
- // never called by system components
- /*package*/ void setBluetoothScoOnByApp(boolean on) {
- synchronized (mDeviceStateLock) {
- mForcedUseForCommExt = on ? AudioSystem.FORCE_BT_SCO : AudioSystem.FORCE_NONE;
- }
- }
- /*package*/ boolean isBluetoothScoOnForApp() {
- synchronized (mDeviceStateLock) {
- return mForcedUseForCommExt == AudioSystem.FORCE_BT_SCO;
- }
- }
+ /**
+ * Current Bluetooth SCO audio active state indicated by BtHelper via setBluetoothScoOn().
+ */
+ private boolean mBluetoothScoOn;
/*package*/ void setBluetoothScoOn(boolean on, String eventSource) {
- //Log.i(TAG, "setBluetoothScoOn: " + on + " " + eventSource);
- synchronized (mDeviceStateLock) {
- if (on) {
- // do not accept SCO ON if SCO audio is not connected
- if (!mBtHelper.isBluetoothScoOn()) {
- mForcedUseForCommExt = AudioSystem.FORCE_BT_SCO;
- return;
- }
- mForcedUseForComm = AudioSystem.FORCE_BT_SCO;
- } else if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) {
- mForcedUseForComm = isSpeakerphoneOnRequested()
- ? AudioSystem.FORCE_SPEAKER : AudioSystem.FORCE_NONE;
- }
- mForcedUseForCommExt = mForcedUseForComm;
- AudioSystem.setParameters("BT_SCO=" + (on ? "on" : "off"));
- sendIILMsgNoDelay(MSG_IIL_SET_FORCE_USE, SENDMSG_QUEUE,
- AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, eventSource);
- sendIILMsgNoDelay(MSG_IIL_SET_FORCE_USE, SENDMSG_QUEUE,
- AudioSystem.FOR_RECORD, mForcedUseForComm, eventSource);
+ if (AudioService.DEBUG_COMM_RTE) {
+ Log.v(TAG, "setBluetoothScoOn: " + on + " " + eventSource);
}
- // Un-mute ringtone stream volume
- mAudioService.postUpdateRingerModeServiceInt();
+ synchronized (mDeviceStateLock) {
+ mBluetoothScoOn = on;
+ sendLMsgNoDelay(MSG_L_UPDATE_COMMUNICATION_ROUTE, SENDMSG_QUEUE, eventSource);
+ }
+ }
+
+ /**
+ * Indicates if active route selection for communication is Bluetooth SCO.
+ * @return true if Bluetooth SCO is active , false otherwise.
+ */
+ /*package*/ boolean isBluetoothScoOn() {
+ return getForcedUseForComm() == AudioSystem.FORCE_BT_SCO;
}
/*package*/ AudioRoutesInfo startWatchingRoutes(IAudioRoutesObserver observer) {
@@ -509,22 +554,43 @@
sendLMsgNoDelay(MSG_L_A2DP_DEVICE_CONFIG_CHANGE, SENDMSG_QUEUE, device);
}
- @GuardedBy("mSetModeLock")
- /*package*/ void startBluetoothScoForClient_Sync(IBinder cb, int scoAudioMode,
+ /*package*/ void startBluetoothScoForClient(IBinder cb, int pid, int scoAudioMode,
@NonNull String eventSource) {
- synchronized (mDeviceStateLock) {
- // Cancel speakerphone ON request by this same client: speakerphone and BT SCO routes
- // are mutually exclusive.
- // See symmetrical operation for setSpeakerphoneOn(true).
- setSpeakerphoneOffForPid(Binder.getCallingPid());
- mBtHelper.startBluetoothScoForClient(cb, scoAudioMode, eventSource);
+
+ if (AudioService.DEBUG_COMM_RTE) {
+ Log.v(TAG, "startBluetoothScoForClient_Sync, pid: " + pid);
+ }
+
+ synchronized (mSetModeLock) {
+ synchronized (mDeviceStateLock) {
+ AudioDeviceAttributes device = new AudioDeviceAttributes(
+ AudioDeviceAttributes.ROLE_OUTPUT, AudioDeviceInfo.TYPE_BLUETOOTH_SCO, "");
+ setCommunicationRouteForClient(cb, pid, device, scoAudioMode, eventSource);
+ if (!isBluetoothScoRequested()) {
+ Log.w(TAG, "startBluetoothScoForClient_Sync: rejected for pid: "
+ + pid + " mode owner pid: " + mModeOwnerPid);
+ postBroadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
+ }
+ }
}
}
- @GuardedBy("mSetModeLock")
- /*package*/ void stopBluetoothScoForClient_Sync(IBinder cb, @NonNull String eventSource) {
- synchronized (mDeviceStateLock) {
- mBtHelper.stopBluetoothScoForClient(cb, eventSource);
+ /*package*/ void stopBluetoothScoForClient(
+ IBinder cb, int pid, @NonNull String eventSource) {
+
+ if (AudioService.DEBUG_COMM_RTE) {
+ Log.v(TAG, "stopBluetoothScoForClient_Sync, pid: " + pid);
+ }
+
+ synchronized (mSetModeLock) {
+ synchronized (mDeviceStateLock) {
+ CommunicationRouteClient client = getCommunicationRouteClientForPid(pid);
+ if (client == null || !client.requestsBluetoothSco()) {
+ return;
+ }
+ setCommunicationRouteForClient(
+ cb, pid, null, BtHelper.SCO_MODE_UNDEFINED, eventSource);
+ }
}
}
@@ -696,12 +762,8 @@
hearingAidProfile);
}
- /*package*/ void postScoClientDied(Object obj) {
- sendLMsgNoDelay(MSG_L_SCOCLIENT_DIED, SENDMSG_QUEUE, obj);
- }
-
- /*package*/ void postSpeakerphoneClientDied(Object obj) {
- sendLMsgNoDelay(MSG_L_SPEAKERPHONE_CLIENT_DIED, SENDMSG_QUEUE, obj);
+ /*package*/ void postCommunicationRouteClientDied(CommunicationRouteClient client) {
+ sendLMsgNoDelay(MSG_L_COMMUNICATION_ROUTE_CLIENT_DIED, SENDMSG_QUEUE, client);
}
/*package*/ void postSaveSetPreferredDevicesForStrategy(int strategy,
@@ -821,15 +883,14 @@
mDeviceInventory.dump(pw, prefix);
+ pw.println("\n" + prefix + "Communication route clients:");
+ mCommunicationRouteClients.forEach((cl) -> {
+ pw.println(" " + prefix + "pid: " + cl.getPid() + " device: "
+ + cl.getDevice() + " cb: " + cl.getBinder()); });
+
pw.println("\n" + prefix + "mForcedUseForComm: "
+ AudioSystem.forceUseConfigToString(mForcedUseForComm));
- pw.println(prefix + "mForcedUseForCommExt: "
- + AudioSystem.forceUseConfigToString(mForcedUseForCommExt));
pw.println(prefix + "mModeOwnerPid: " + mModeOwnerPid);
- pw.println(prefix + "Speakerphone clients:");
- mSpeakerphoneClients.forEach((cl) -> {
- pw.println(" " + prefix + "pid: " + cl.getPid() + " on: "
- + cl.isOn() + " cb: " + cl.getBinder()); });
mBtHelper.dump(pw, prefix);
}
@@ -852,6 +913,11 @@
.set(MediaMetrics.Property.FORCE_USE_MODE,
AudioSystem.forceUseConfigToString(config))
.record();
+
+ if (AudioService.DEBUG_COMM_RTE) {
+ Log.v(TAG, "onSetForceUse(useCase<" + useCase + ">, config<" + config + ">, fromA2dp<"
+ + fromA2dp + ">, eventSource<" + eventSource + ">)");
+ }
AudioSystem.setForceUse(useCase, config);
}
@@ -917,9 +983,12 @@
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_RESTORE_DEVICES:
- synchronized (mDeviceStateLock) {
- mDeviceInventory.onRestoreDevices();
- mBtHelper.onAudioServerDiedRestoreA2dp();
+ synchronized (mSetModeLock) {
+ synchronized (mDeviceStateLock) {
+ mDeviceInventory.onRestoreDevices();
+ mBtHelper.onAudioServerDiedRestoreA2dp();
+ onUpdateCommunicationRoute("MSG_RESTORE_DEVICES");
+ }
}
break;
case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE:
@@ -1009,25 +1078,24 @@
if (mModeOwnerPid != msg.arg1) {
mModeOwnerPid = msg.arg1;
if (msg.arg2 != AudioSystem.MODE_RINGTONE) {
- updateSpeakerphoneOn("setNewModeOwner");
- }
- if (mModeOwnerPid != 0) {
- mBtHelper.disconnectBluetoothSco(mModeOwnerPid);
+ onUpdateCommunicationRoute("setNewModeOwner");
}
}
}
}
break;
- case MSG_L_SCOCLIENT_DIED:
+ case MSG_L_COMMUNICATION_ROUTE_CLIENT_DIED:
synchronized (mSetModeLock) {
synchronized (mDeviceStateLock) {
- mBtHelper.scoClientDied(msg.obj);
+ onCommunicationRouteClientDied((CommunicationRouteClient) msg.obj);
}
}
break;
- case MSG_L_SPEAKERPHONE_CLIENT_DIED:
- synchronized (mDeviceStateLock) {
- speakerphoneClientDied(msg.obj);
+ case MSG_L_UPDATE_COMMUNICATION_ROUTE:
+ synchronized (mSetModeLock) {
+ synchronized (mDeviceStateLock) {
+ onUpdateCommunicationRoute((String) msg.obj);
+ }
}
break;
case MSG_TOGGLE_HDMI:
@@ -1207,17 +1275,17 @@
// process external command to (dis)connect a hearing aid device
private static final int MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT = 31;
- // a ScoClient died in BtHelper
- private static final int MSG_L_SCOCLIENT_DIED = 32;
- private static final int MSG_IL_SAVE_PREF_DEVICES_FOR_STRATEGY = 33;
- private static final int MSG_I_SAVE_REMOVE_PREF_DEVICES_FOR_STRATEGY = 34;
+ private static final int MSG_IL_SAVE_PREF_DEVICES_FOR_STRATEGY = 32;
+ private static final int MSG_I_SAVE_REMOVE_PREF_DEVICES_FOR_STRATEGY = 33;
- private static final int MSG_L_SPEAKERPHONE_CLIENT_DIED = 35;
- private static final int MSG_CHECK_MUTE_MUSIC = 36;
- private static final int MSG_REPORT_NEW_ROUTES_A2DP = 37;
+ private static final int MSG_L_COMMUNICATION_ROUTE_CLIENT_DIED = 34;
+ private static final int MSG_CHECK_MUTE_MUSIC = 35;
+ private static final int MSG_REPORT_NEW_ROUTES_A2DP = 36;
- private static final int MSG_IL_SAVE_PREF_DEVICES_FOR_CAPTURE_PRESET = 38;
- private static final int MSG_I_SAVE_CLEAR_PREF_DEVICES_FOR_CAPTURE_PRESET = 39;
+ private static final int MSG_IL_SAVE_PREF_DEVICES_FOR_CAPTURE_PRESET = 37;
+ private static final int MSG_I_SAVE_CLEAR_PREF_DEVICES_FOR_CAPTURE_PRESET = 38;
+
+ private static final int MSG_L_UPDATE_COMMUNICATION_ROUTE = 39;
private static boolean isMessageHandledUnderWakelock(int msgId) {
@@ -1372,14 +1440,20 @@
}
}
- private class SpeakerphoneClient implements IBinder.DeathRecipient {
+ // List of applications requesting a specific route for communication.
+ @GuardedBy("mDeviceStateLock")
+ private final @NonNull LinkedList<CommunicationRouteClient> mCommunicationRouteClients =
+ new LinkedList<CommunicationRouteClient>();
+
+ private class CommunicationRouteClient implements IBinder.DeathRecipient {
private final IBinder mCb;
private final int mPid;
- private final boolean mOn;
- SpeakerphoneClient(IBinder cb, int pid, boolean on) {
+ private AudioDeviceAttributes mDevice;
+
+ CommunicationRouteClient(IBinder cb, int pid, AudioDeviceAttributes device) {
mCb = cb;
mPid = pid;
- mOn = on;
+ mDevice = device;
}
public boolean registerDeathRecipient() {
@@ -1388,7 +1462,7 @@
mCb.linkToDeath(this, 0);
status = true;
} catch (RemoteException e) {
- Log.w(TAG, "SpeakerphoneClient could not link to " + mCb + " binder death");
+ Log.w(TAG, "CommunicationRouteClient could not link to " + mCb + " binder death");
}
return status;
}
@@ -1397,13 +1471,13 @@
try {
mCb.unlinkToDeath(this, 0);
} catch (NoSuchElementException e) {
- Log.w(TAG, "SpeakerphoneClient could not not unregistered to binder");
+ Log.w(TAG, "CommunicationRouteClient could not not unregistered to binder");
}
}
@Override
public void binderDied() {
- postSpeakerphoneClientDied(this);
+ postCommunicationRouteClientDied(this);
}
IBinder getBinder() {
@@ -1414,29 +1488,99 @@
return mPid;
}
- boolean isOn() {
- return mOn;
+ AudioDeviceAttributes getDevice() {
+ return mDevice;
+ }
+
+ boolean requestsBluetoothSco() {
+ return mDevice != null
+ && mDevice.getType()
+ == AudioDeviceInfo.TYPE_BLUETOOTH_SCO;
+ }
+
+ boolean requestsSpeakerphone() {
+ return mDevice != null
+ && mDevice.getType()
+ == AudioDeviceInfo.TYPE_BUILTIN_SPEAKER;
}
}
+ // @GuardedBy("mSetModeLock")
@GuardedBy("mDeviceStateLock")
- private void speakerphoneClientDied(Object obj) {
- if (obj == null) {
+ private void onCommunicationRouteClientDied(CommunicationRouteClient client) {
+ if (client == null) {
return;
}
Log.w(TAG, "Speaker client died");
- if (removeSpeakerphoneClient(((SpeakerphoneClient) obj).getBinder(), false) != null) {
- updateSpeakerphoneOn("speakerphoneClientDied");
+ if (removeCommunicationRouteClient(client.getBinder(), false)
+ != null) {
+ onUpdateCommunicationRoute("onCommunicationRouteClientDied");
}
}
- private SpeakerphoneClient removeSpeakerphoneClient(IBinder cb, boolean unregister) {
- for (SpeakerphoneClient cl : mSpeakerphoneClients) {
+ /**
+ * Determines which forced usage for communication should be sent to audio policy manager
+ * as a function of current SCO audio activation state and active communication route requests.
+ * SCO audio state has the highest priority as it can result from external activation by
+ * telephony service.
+ * @return selected forced usage for communication.
+ */
+ @GuardedBy("mDeviceStateLock")
+ private int getForcedUseForComm() {
+ boolean btSCoOn = mBluetoothScoOn && mBtHelper.isBluetoothScoOn();
+
+ if (btSCoOn) {
+ return AudioSystem.FORCE_BT_SCO;
+ }
+ if (isSpeakerphoneRequested()) {
+ return AudioSystem.FORCE_SPEAKER;
+ }
+ return AudioSystem.FORCE_NONE;
+ }
+
+ /**
+ * Configures audio policy manager and audio HAL according to active communication route.
+ * Always called from message Handler.
+ */
+ // @GuardedBy("mSetModeLock")
+ @GuardedBy("mDeviceStateLock")
+ private void onUpdateCommunicationRoute(String eventSource) {
+ mForcedUseForComm = getForcedUseForComm();
+
+ if (AudioService.DEBUG_COMM_RTE) {
+ Log.v(TAG, "onUpdateCommunicationRoute, mForcedUseForComm: " + mForcedUseForComm
+ + " eventSource: " + eventSource);
+ }
+
+ if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) {
+ AudioSystem.setParameters("BT_SCO=on");
+ setForceUse_Async(
+ AudioSystem.FOR_COMMUNICATION, AudioSystem.FORCE_BT_SCO, eventSource);
+ setForceUse_Async(
+ AudioSystem.FOR_RECORD, AudioSystem.FORCE_BT_SCO, eventSource);
+ } else {
+ AudioSystem.setParameters("BT_SCO=off");
+ setForceUse_Async(
+ AudioSystem.FOR_RECORD, AudioSystem.FORCE_NONE, eventSource);
+ if (mForcedUseForComm == AudioSystem.FORCE_SPEAKER) {
+ setForceUse_Async(
+ AudioSystem.FOR_COMMUNICATION, AudioSystem.FORCE_SPEAKER, eventSource);
+ } else {
+ setForceUse_Async(
+ AudioSystem.FOR_COMMUNICATION, AudioSystem.FORCE_NONE, eventSource);
+ }
+ }
+ mAudioService.postUpdateRingerModeServiceInt();
+ }
+
+ private CommunicationRouteClient removeCommunicationRouteClient(
+ IBinder cb, boolean unregister) {
+ for (CommunicationRouteClient cl : mCommunicationRouteClients) {
if (cl.getBinder() == cb) {
if (unregister) {
cl.unregisterDeathRecipient();
}
- mSpeakerphoneClients.remove(cl);
+ mCommunicationRouteClients.remove(cl);
return cl;
}
}
@@ -1444,30 +1588,25 @@
}
@GuardedBy("mDeviceStateLock")
- private boolean addSpeakerphoneClient(IBinder cb, int pid, boolean on) {
+ private CommunicationRouteClient addCommunicationRouteClient(
+ IBinder cb, int pid, AudioDeviceAttributes device) {
// always insert new request at first position
- removeSpeakerphoneClient(cb, true);
- SpeakerphoneClient client = new SpeakerphoneClient(cb, pid, on);
+ removeCommunicationRouteClient(cb, true);
+ CommunicationRouteClient client = new CommunicationRouteClient(cb, pid, device);
if (client.registerDeathRecipient()) {
- mSpeakerphoneClients.add(0, client);
- return true;
+ mCommunicationRouteClients.add(0, client);
+ return client;
}
- return false;
+ return null;
}
@GuardedBy("mDeviceStateLock")
- private SpeakerphoneClient getSpeakerphoneClientForPid(int pid) {
- for (SpeakerphoneClient cl : mSpeakerphoneClients) {
+ private CommunicationRouteClient getCommunicationRouteClientForPid(int pid) {
+ for (CommunicationRouteClient cl : mCommunicationRouteClients) {
if (cl.getPid() == pid) {
return cl;
}
}
return null;
}
-
- // List of clients requesting speakerPhone ON
- @GuardedBy("mDeviceStateLock")
- private final @NonNull ArrayList<SpeakerphoneClient> mSpeakerphoneClients =
- new ArrayList<SpeakerphoneClient>();
-
}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index ff6367b..662d8d5 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -207,6 +207,9 @@
/** debug calls to devices APIs */
protected static final boolean DEBUG_DEVICES = false;
+ /** Debug communication route */
+ protected static final boolean DEBUG_COMM_RTE = false;
+
/** How long to delay before persisting a change in volume/ringer mode. */
private static final int PERSIST_DELAY = 500;
@@ -3765,7 +3768,7 @@
final boolean ringerModeMute = ringerMode == AudioManager.RINGER_MODE_VIBRATE
|| ringerMode == AudioManager.RINGER_MODE_SILENT;
final boolean shouldRingSco = ringerMode == AudioManager.RINGER_MODE_VIBRATE
- && isBluetoothScoOn();
+ && mDeviceBroker.isBluetoothScoOn();
// Ask audio policy engine to force use Bluetooth SCO channel if needed
final String eventSource = "muteRingerModeStreams() from u/pid:" + Binder.getCallingUid()
+ "/" + Binder.getCallingPid();
@@ -4406,10 +4409,10 @@
// for logging only
final int uid = Binder.getCallingUid();
final int pid = Binder.getCallingPid();
+
final String eventSource = new StringBuilder("setSpeakerphoneOn(").append(on)
.append(") from u/pid:").append(uid).append("/")
.append(pid).toString();
- final boolean stateChanged = mDeviceBroker.setSpeakerphoneOn(cb, pid, on, eventSource);
new MediaMetrics.Item(MediaMetrics.Name.AUDIO_DEVICE
+ MediaMetrics.SEPARATOR + "setSpeakerphoneOn")
.setUid(uid)
@@ -4417,17 +4420,9 @@
.set(MediaMetrics.Property.STATE, on
? MediaMetrics.Value.ON : MediaMetrics.Value.OFF)
.record();
-
- if (stateChanged) {
- final long ident = Binder.clearCallingIdentity();
- try {
- mContext.sendBroadcastAsUser(
- new Intent(AudioManager.ACTION_SPEAKERPHONE_STATE_CHANGED)
- .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY), UserHandle.ALL);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
+ final long ident = Binder.clearCallingIdentity();
+ mDeviceBroker.setSpeakerphoneOn(cb, pid, on, eventSource);
+ Binder.restoreCallingIdentity(ident);
}
/** @see AudioManager#isSpeakerphoneOn() */
@@ -4435,6 +4430,11 @@
return mDeviceBroker.isSpeakerphoneOn();
}
+
+ /** BT SCO audio state seen by apps using the deprecated API setBluetoothScoOn().
+ * @see isBluetoothScoOn() */
+ private boolean mBtScoOnByApp;
+
/** @see AudioManager#setBluetoothScoOn(boolean) */
public void setBluetoothScoOn(boolean on) {
if (!checkAudioSettingsPermission("setBluetoothScoOn()")) {
@@ -4443,7 +4443,7 @@
// Only enable calls from system components
if (UserHandle.getCallingAppId() >= FIRST_APPLICATION_UID) {
- mDeviceBroker.setBluetoothScoOnByApp(on);
+ mBtScoOnByApp = on;
return;
}
@@ -4469,7 +4469,7 @@
* Note that it doesn't report internal state, but state seen by apps (which may have
* called setBluetoothScoOn() */
public boolean isBluetoothScoOn() {
- return mDeviceBroker.isBluetoothScoOnForApp();
+ return mBtScoOnByApp || mDeviceBroker.isBluetoothScoOn();
}
// TODO investigate internal users due to deprecation of SDK API
@@ -4516,7 +4516,7 @@
.set(MediaMetrics.Property.SCO_AUDIO_MODE,
BtHelper.scoAudioModeToString(scoAudioMode))
.record();
- startBluetoothScoInt(cb, scoAudioMode, eventSource);
+ startBluetoothScoInt(cb, pid, scoAudioMode, eventSource);
}
@@ -4535,10 +4535,10 @@
.set(MediaMetrics.Property.SCO_AUDIO_MODE,
BtHelper.scoAudioModeToString(BtHelper.SCO_MODE_VIRTUAL_CALL))
.record();
- startBluetoothScoInt(cb, BtHelper.SCO_MODE_VIRTUAL_CALL, eventSource);
+ startBluetoothScoInt(cb, pid, BtHelper.SCO_MODE_VIRTUAL_CALL, eventSource);
}
- void startBluetoothScoInt(IBinder cb, int scoAudioMode, @NonNull String eventSource) {
+ void startBluetoothScoInt(IBinder cb, int pid, int scoAudioMode, @NonNull String eventSource) {
MediaMetrics.Item mmi = new MediaMetrics.Item(MediaMetrics.Name.AUDIO_BLUETOOTH)
.set(MediaMetrics.Property.EVENT, "startBluetoothScoInt")
.set(MediaMetrics.Property.SCO_AUDIO_MODE,
@@ -4549,9 +4549,9 @@
mmi.set(MediaMetrics.Property.EARLY_RETURN, "permission or systemReady").record();
return;
}
- synchronized (mDeviceBroker.mSetModeLock) {
- mDeviceBroker.startBluetoothScoForClient_Sync(cb, scoAudioMode, eventSource);
- }
+ final long ident = Binder.clearCallingIdentity();
+ mDeviceBroker.startBluetoothScoForClient(cb, pid, scoAudioMode, eventSource);
+ Binder.restoreCallingIdentity(ident);
mmi.record();
}
@@ -4566,9 +4566,9 @@
final String eventSource = new StringBuilder("stopBluetoothSco()")
.append(") from u/pid:").append(uid).append("/")
.append(pid).toString();
- synchronized (mDeviceBroker.mSetModeLock) {
- mDeviceBroker.stopBluetoothScoForClient_Sync(cb, eventSource);
- }
+ final long ident = Binder.clearCallingIdentity();
+ mDeviceBroker.stopBluetoothScoForClient(cb, pid, eventSource);
+ Binder.restoreCallingIdentity(ident);
new MediaMetrics.Item(MediaMetrics.Name.AUDIO_BLUETOOTH)
.setUid(uid)
.setPid(pid)
@@ -7848,6 +7848,7 @@
pw.print(" mHasVibrator="); pw.println(mHasVibrator);
pw.print(" mVolumePolicy="); pw.println(mVolumePolicy);
pw.print(" mAvrcpAbsVolSupported="); pw.println(mAvrcpAbsVolSupported);
+ pw.print(" mBtScoOnByApp="); pw.println(mBtScoOnByApp);
pw.print(" mIsSingleVolume="); pw.println(mIsSingleVolume);
pw.print(" mUseFixedVolume="); pw.println(mUseFixedVolume);
pw.print(" mFixedVolumeDevices="); pw.println(dumpDeviceTypes(mFixedVolumeDevices));
diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java
index 8de31d9..ae0e805 100644
--- a/services/core/java/com/android/server/audio/BtHelper.java
+++ b/services/core/java/com/android/server/audio/BtHelper.java
@@ -30,8 +30,6 @@
import android.media.AudioManager;
import android.media.AudioSystem;
import android.os.Binder;
-import android.os.IBinder;
-import android.os.RemoteException;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.Log;
@@ -39,9 +37,7 @@
import com.android.internal.annotations.GuardedBy;
import java.io.PrintWriter;
-import java.util.ArrayList;
import java.util.List;
-import java.util.NoSuchElementException;
import java.util.Objects;
/**
@@ -58,10 +54,6 @@
mDeviceBroker = broker;
}
- // List of clients having issued a SCO start request
- @GuardedBy("BtHelper.this")
- private final @NonNull ArrayList<ScoClient> mScoClients = new ArrayList<ScoClient>();
-
// BluetoothHeadset API to control SCO connection
private @Nullable BluetoothHeadset mBluetoothHeadset;
@@ -301,6 +293,8 @@
@GuardedBy("AudioDeviceBroker.mDeviceStateLock")
/*package*/ synchronized void receiveBtEvent(Intent intent) {
final String action = intent.getAction();
+
+ Log.i(TAG, "receiveBtEvent action: " + action + " mScoAudioState: " + mScoAudioState);
if (action.equals(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED)) {
BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
setBtScoActiveDevice(btDevice);
@@ -308,20 +302,16 @@
boolean broadcast = false;
int scoAudioState = AudioManager.SCO_AUDIO_STATE_ERROR;
int btState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1);
- // broadcast intent if the connection was initated by AudioService
- if (!mScoClients.isEmpty()
- && (mScoAudioState == SCO_STATE_ACTIVE_INTERNAL
- || mScoAudioState == SCO_STATE_ACTIVATE_REQ
- || mScoAudioState == SCO_STATE_DEACTIVATE_REQ
- || mScoAudioState == SCO_STATE_DEACTIVATING)) {
- broadcast = true;
- }
+ Log.i(TAG, "receiveBtEvent ACTION_AUDIO_STATE_CHANGED: " + btState);
switch (btState) {
case BluetoothHeadset.STATE_AUDIO_CONNECTED:
scoAudioState = AudioManager.SCO_AUDIO_STATE_CONNECTED;
if (mScoAudioState != SCO_STATE_ACTIVE_INTERNAL
&& mScoAudioState != SCO_STATE_DEACTIVATE_REQ) {
mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL;
+ } else if (mDeviceBroker.isBluetoothScoRequested()) {
+ // broadcast intent if the connection was initated by AudioService
+ broadcast = true;
}
mDeviceBroker.setBluetoothScoOn(true, "BtHelper.receiveBtEvent");
break;
@@ -333,21 +323,21 @@
// notified by requestScoState() setting state to SCO_STATE_ACTIVATE_REQ.
// 2) If audio was connected then disconnected via Bluetooth APIs and
// we still have pending activation requests by apps: this is indicated by
- // state SCO_STATE_ACTIVE_EXTERNAL and the mScoClients list not empty.
+ // state SCO_STATE_ACTIVE_EXTERNAL and BT SCO is requested.
if (mScoAudioState == SCO_STATE_ACTIVATE_REQ
|| (mScoAudioState == SCO_STATE_ACTIVE_EXTERNAL
- && !mScoClients.isEmpty())) {
+ && mDeviceBroker.isBluetoothScoRequested())) {
if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null
&& connectBluetoothScoAudioHelper(mBluetoothHeadset,
mBluetoothHeadsetDevice, mScoAudioMode)) {
mScoAudioState = SCO_STATE_ACTIVE_INTERNAL;
- broadcast = false;
+ scoAudioState = AudioManager.SCO_AUDIO_STATE_CONNECTING;
+ broadcast = true;
break;
}
}
- // Tear down SCO if disconnected from external
- if (mScoAudioState == SCO_STATE_DEACTIVATING) {
- clearAllScoClients(0, false);
+ if (mScoAudioState != SCO_STATE_ACTIVE_EXTERNAL) {
+ broadcast = true;
}
mScoAudioState = SCO_STATE_INACTIVE;
break;
@@ -356,11 +346,8 @@
&& mScoAudioState != SCO_STATE_DEACTIVATE_REQ) {
mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL;
}
- broadcast = false;
break;
default:
- // do not broadcast CONNECTING or invalid state
- broadcast = false;
break;
}
if (broadcast) {
@@ -386,81 +373,19 @@
== BluetoothHeadset.STATE_AUDIO_CONNECTED;
}
- /**
- * Disconnect all SCO connections started by {@link AudioManager} except those started by
- * {@param exceptPid}
- *
- * @param exceptPid pid whose SCO connections through {@link AudioManager} should be kept
- */
// @GuardedBy("AudioDeviceBroker.mSetModeLock")
@GuardedBy("AudioDeviceBroker.mDeviceStateLock")
- /*package*/ synchronized void disconnectBluetoothSco(int exceptPid) {
- checkScoAudioState();
- if (mScoAudioState == SCO_STATE_ACTIVE_EXTERNAL) {
- return;
- }
- clearAllScoClients(exceptPid, true);
- }
-
- // @GuardedBy("AudioDeviceBroker.mSetModeLock")
- @GuardedBy("AudioDeviceBroker.mDeviceStateLock")
- /*package*/ synchronized void startBluetoothScoForClient(IBinder cb, int scoAudioMode,
+ /*package*/ synchronized boolean startBluetoothSco(int scoAudioMode,
@NonNull String eventSource) {
- ScoClient client = getScoClient(cb, true);
- // The calling identity must be cleared before calling ScoClient.incCount().
- // inCount() calls requestScoState() which in turn can call BluetoothHeadset APIs
- // and this must be done on behalf of system server to make sure permissions are granted.
- // The caller identity must be cleared after getScoClient() because it is needed if a new
- // client is created.
- final long ident = Binder.clearCallingIdentity();
- try {
- AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(eventSource));
- client.requestScoState(BluetoothHeadset.STATE_AUDIO_CONNECTED, scoAudioMode);
- } catch (NullPointerException e) {
- Log.e(TAG, "Null ScoClient", e);
- }
- Binder.restoreCallingIdentity(ident);
- }
-
- // @GuardedBy("AudioDeviceBroker.mSetModeLock")
- @GuardedBy("AudioDeviceBroker.mDeviceStateLock")
- /*package*/ synchronized void stopBluetoothScoForClient(IBinder cb,
- @NonNull String eventSource) {
- ScoClient client = getScoClient(cb, false);
- // The calling identity must be cleared before calling ScoClient.decCount().
- // decCount() calls requestScoState() which in turn can call BluetoothHeadset APIs
- // and this must be done on behalf of system server to make sure permissions are granted.
- final long ident = Binder.clearCallingIdentity();
- if (client != null) {
- stopAndRemoveClient(client, eventSource);
- }
- Binder.restoreCallingIdentity(ident);
- }
-
- // @GuardedBy("AudioDeviceBroker.mSetModeLock")
- @GuardedBy("AudioDeviceBroker.mDeviceStateLock")
- /*package*/ synchronized void stopBluetoothScoForPid(int pid) {
- ScoClient client = getScoClientForPid(pid);
- if (client == null) {
- return;
- }
- final String eventSource = new StringBuilder("stopBluetoothScoForPid(")
- .append(pid).append(")").toString();
- stopAndRemoveClient(client, eventSource);
- }
-
- @GuardedBy("AudioDeviceBroker.mDeviceStateLock")
- // @GuardedBy("BtHelper.this")
- private void stopAndRemoveClient(ScoClient client, @NonNull String eventSource) {
AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(eventSource));
- client.requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED,
- SCO_MODE_VIRTUAL_CALL);
- // If a disconnection is pending, the client will be removed when clearAllScoClients()
- // is called form receiveBtEvent()
- if (mScoAudioState != SCO_STATE_DEACTIVATE_REQ
- && mScoAudioState != SCO_STATE_DEACTIVATING) {
- client.remove(false /*stop */, true /*unregister*/);
- }
+ return requestScoState(BluetoothHeadset.STATE_AUDIO_CONNECTED, scoAudioMode);
+ }
+
+ // @GuardedBy("AudioDeviceBroker.mSetModeLock")
+ @GuardedBy("AudioDeviceBroker.mDeviceStateLock")
+ /*package*/ synchronized boolean stopBluetoothSco(@NonNull String eventSource) {
+ AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(eventSource));
+ return requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED, SCO_MODE_VIRTUAL_CALL);
}
/*package*/ synchronized void setHearingAidVolume(int index, int streamType) {
@@ -507,7 +432,6 @@
// @GuardedBy("AudioDeviceBroker.mSetModeLock")
@GuardedBy("AudioDeviceBroker.mDeviceStateLock")
/*package*/ synchronized void resetBluetoothSco() {
- clearAllScoClients(0, false);
mScoAudioState = SCO_STATE_INACTIVE;
broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
AudioSystem.setParameters("A2dpSuspended=false");
@@ -740,196 +664,122 @@
};
//----------------------------------------------------------------------
+
// @GuardedBy("AudioDeviceBroker.mSetModeLock")
- @GuardedBy("AudioDeviceBroker.mDeviceStateLock")
- /*package*/ synchronized void scoClientDied(Object obj) {
- final ScoClient client = (ScoClient) obj;
- client.remove(true /*stop*/, false /*unregister*/);
- Log.w(TAG, "SCO client died");
- }
-
- private class ScoClient implements IBinder.DeathRecipient {
- private IBinder mCb; // To be notified of client's death
- private int mCreatorPid;
-
- ScoClient(IBinder cb) {
- mCb = cb;
- mCreatorPid = Binder.getCallingPid();
- }
-
- public void registerDeathRecipient() {
- try {
- mCb.linkToDeath(this, 0);
- } catch (RemoteException e) {
- Log.w(TAG, "ScoClient could not link to " + mCb + " binder death");
- }
- }
-
- public void unregisterDeathRecipient() {
- try {
- mCb.unlinkToDeath(this, 0);
- } catch (NoSuchElementException e) {
- Log.w(TAG, "ScoClient could not not unregistered to binder");
- }
- }
-
- @Override
- public void binderDied() {
- // process this from DeviceBroker's message queue to take the right locks since
- // this event can impact SCO mode and requires querying audio mode stack
- mDeviceBroker.postScoClientDied(this);
- }
-
- IBinder getBinder() {
- return mCb;
- }
-
- int getPid() {
- return mCreatorPid;
- }
-
- // @GuardedBy("AudioDeviceBroker.mSetModeLock")
- //@GuardedBy("AudioDeviceBroker.mDeviceStateLock")
- @GuardedBy("BtHelper.this")
- private boolean requestScoState(int state, int scoAudioMode) {
- checkScoAudioState();
- if (mScoClients.size() != 1) {
- Log.i(TAG, "requestScoState: state=" + state + ", scoAudioMode=" + scoAudioMode
- + ", num SCO clients=" + mScoClients.size());
- return true;
- }
- if (state == BluetoothHeadset.STATE_AUDIO_CONNECTED) {
- // Make sure that the state transitions to CONNECTING even if we cannot initiate
- // the connection.
- broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTING);
- // Accept SCO audio activation only in NORMAL audio mode or if the mode is
- // currently controlled by the same client process.
- final int modeOwnerPid = mDeviceBroker.getModeOwnerPid();
- if (modeOwnerPid != 0 && (modeOwnerPid != mCreatorPid)) {
- Log.w(TAG, "requestScoState: audio mode is not NORMAL and modeOwnerPid "
- + modeOwnerPid + " != creatorPid " + mCreatorPid);
+ //@GuardedBy("AudioDeviceBroker.mDeviceStateLock")
+ @GuardedBy("BtHelper.this")
+ private boolean requestScoState(int state, int scoAudioMode) {
+ checkScoAudioState();
+ if (state == BluetoothHeadset.STATE_AUDIO_CONNECTED) {
+ // Make sure that the state transitions to CONNECTING even if we cannot initiate
+ // the connection.
+ broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTING);
+ switch (mScoAudioState) {
+ case SCO_STATE_INACTIVE:
+ mScoAudioMode = scoAudioMode;
+ if (scoAudioMode == SCO_MODE_UNDEFINED) {
+ mScoAudioMode = SCO_MODE_VIRTUAL_CALL;
+ if (mBluetoothHeadsetDevice != null) {
+ mScoAudioMode = Settings.Global.getInt(
+ mDeviceBroker.getContentResolver(),
+ "bluetooth_sco_channel_"
+ + mBluetoothHeadsetDevice.getAddress(),
+ SCO_MODE_VIRTUAL_CALL);
+ if (mScoAudioMode > SCO_MODE_MAX || mScoAudioMode < 0) {
+ mScoAudioMode = SCO_MODE_VIRTUAL_CALL;
+ }
+ }
+ }
+ if (mBluetoothHeadset == null) {
+ if (getBluetoothHeadset()) {
+ mScoAudioState = SCO_STATE_ACTIVATE_REQ;
+ } else {
+ Log.w(TAG, "requestScoState: getBluetoothHeadset failed during"
+ + " connection, mScoAudioMode=" + mScoAudioMode);
+ broadcastScoConnectionState(
+ AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
+ return false;
+ }
+ break;
+ }
+ if (mBluetoothHeadsetDevice == null) {
+ Log.w(TAG, "requestScoState: no active device while connecting,"
+ + " mScoAudioMode=" + mScoAudioMode);
+ broadcastScoConnectionState(
+ AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
+ return false;
+ }
+ if (connectBluetoothScoAudioHelper(mBluetoothHeadset,
+ mBluetoothHeadsetDevice, mScoAudioMode)) {
+ mScoAudioState = SCO_STATE_ACTIVE_INTERNAL;
+ } else {
+ Log.w(TAG, "requestScoState: connect to "
+ + getAnonymizedAddress(mBluetoothHeadsetDevice)
+ + " failed, mScoAudioMode=" + mScoAudioMode);
+ broadcastScoConnectionState(
+ AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
+ return false;
+ }
+ break;
+ case SCO_STATE_DEACTIVATING:
+ mScoAudioState = SCO_STATE_ACTIVATE_REQ;
+ break;
+ case SCO_STATE_DEACTIVATE_REQ:
+ mScoAudioState = SCO_STATE_ACTIVE_INTERNAL;
+ broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTED);
+ break;
+ case SCO_STATE_ACTIVE_INTERNAL:
+ Log.w(TAG, "requestScoState: already in ACTIVE mode, simply return");
+ break;
+ default:
+ Log.w(TAG, "requestScoState: failed to connect in state "
+ + mScoAudioState + ", scoAudioMode=" + scoAudioMode);
broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
return false;
- }
- switch (mScoAudioState) {
- case SCO_STATE_INACTIVE:
- mScoAudioMode = scoAudioMode;
- if (scoAudioMode == SCO_MODE_UNDEFINED) {
- mScoAudioMode = SCO_MODE_VIRTUAL_CALL;
- if (mBluetoothHeadsetDevice != null) {
- mScoAudioMode = Settings.Global.getInt(
- mDeviceBroker.getContentResolver(),
- "bluetooth_sco_channel_"
- + mBluetoothHeadsetDevice.getAddress(),
- SCO_MODE_VIRTUAL_CALL);
- if (mScoAudioMode > SCO_MODE_MAX || mScoAudioMode < 0) {
- mScoAudioMode = SCO_MODE_VIRTUAL_CALL;
- }
- }
- }
- if (mBluetoothHeadset == null) {
- if (getBluetoothHeadset()) {
- mScoAudioState = SCO_STATE_ACTIVATE_REQ;
- } else {
- Log.w(TAG, "requestScoState: getBluetoothHeadset failed during"
- + " connection, mScoAudioMode=" + mScoAudioMode);
- broadcastScoConnectionState(
- AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
- return false;
- }
- break;
- }
- if (mBluetoothHeadsetDevice == null) {
- Log.w(TAG, "requestScoState: no active device while connecting,"
- + " mScoAudioMode=" + mScoAudioMode);
- broadcastScoConnectionState(
- AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
- return false;
- }
- if (connectBluetoothScoAudioHelper(mBluetoothHeadset,
- mBluetoothHeadsetDevice, mScoAudioMode)) {
- mScoAudioState = SCO_STATE_ACTIVE_INTERNAL;
+ }
+ } else if (state == BluetoothHeadset.STATE_AUDIO_DISCONNECTED) {
+ switch (mScoAudioState) {
+ case SCO_STATE_ACTIVE_INTERNAL:
+ if (mBluetoothHeadset == null) {
+ if (getBluetoothHeadset()) {
+ mScoAudioState = SCO_STATE_DEACTIVATE_REQ;
} else {
- Log.w(TAG, "requestScoState: connect to "
- + getAnonymizedAddress(mBluetoothHeadsetDevice)
- + " failed, mScoAudioMode=" + mScoAudioMode);
+ Log.w(TAG, "requestScoState: getBluetoothHeadset failed during"
+ + " disconnection, mScoAudioMode=" + mScoAudioMode);
+ mScoAudioState = SCO_STATE_INACTIVE;
broadcastScoConnectionState(
AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
return false;
}
break;
- case SCO_STATE_DEACTIVATING:
- mScoAudioState = SCO_STATE_ACTIVATE_REQ;
- break;
- case SCO_STATE_DEACTIVATE_REQ:
- mScoAudioState = SCO_STATE_ACTIVE_INTERNAL;
- broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTED);
- break;
- case SCO_STATE_ACTIVE_INTERNAL:
- Log.w(TAG, "requestScoState: already in ACTIVE mode, simply return");
- break;
- default:
- Log.w(TAG, "requestScoState: failed to connect in state "
- + mScoAudioState + ", scoAudioMode=" + scoAudioMode);
- broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
- return false;
- }
- } else if (state == BluetoothHeadset.STATE_AUDIO_DISCONNECTED) {
- switch (mScoAudioState) {
- case SCO_STATE_ACTIVE_INTERNAL:
- if (mBluetoothHeadset == null) {
- if (getBluetoothHeadset()) {
- mScoAudioState = SCO_STATE_DEACTIVATE_REQ;
- } else {
- Log.w(TAG, "requestScoState: getBluetoothHeadset failed during"
- + " disconnection, mScoAudioMode=" + mScoAudioMode);
- mScoAudioState = SCO_STATE_INACTIVE;
- broadcastScoConnectionState(
- AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
- return false;
- }
- break;
- }
- if (mBluetoothHeadsetDevice == null) {
- mScoAudioState = SCO_STATE_INACTIVE;
- broadcastScoConnectionState(
- AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
- break;
- }
- if (disconnectBluetoothScoAudioHelper(mBluetoothHeadset,
- mBluetoothHeadsetDevice, mScoAudioMode)) {
- mScoAudioState = SCO_STATE_DEACTIVATING;
- } else {
- mScoAudioState = SCO_STATE_INACTIVE;
- broadcastScoConnectionState(
- AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
- }
- break;
- case SCO_STATE_ACTIVATE_REQ:
+ }
+ if (mBluetoothHeadsetDevice == null) {
mScoAudioState = SCO_STATE_INACTIVE;
- broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
+ broadcastScoConnectionState(
+ AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
break;
- default:
- Log.w(TAG, "requestScoState: failed to disconnect in state "
- + mScoAudioState + ", scoAudioMode=" + scoAudioMode);
- broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
- return false;
- }
+ }
+ if (disconnectBluetoothScoAudioHelper(mBluetoothHeadset,
+ mBluetoothHeadsetDevice, mScoAudioMode)) {
+ mScoAudioState = SCO_STATE_DEACTIVATING;
+ } else {
+ mScoAudioState = SCO_STATE_INACTIVE;
+ broadcastScoConnectionState(
+ AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
+ }
+ break;
+ case SCO_STATE_ACTIVATE_REQ:
+ mScoAudioState = SCO_STATE_INACTIVE;
+ broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
+ break;
+ default:
+ Log.w(TAG, "requestScoState: failed to disconnect in state "
+ + mScoAudioState + ", scoAudioMode=" + scoAudioMode);
+ broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
+ return false;
}
- return true;
}
-
- @GuardedBy("BtHelper.this")
- void remove(boolean stop, boolean unregister) {
- if (unregister) {
- unregisterDeathRecipient();
- }
- if (stop) {
- requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED,
- SCO_MODE_VIRTUAL_CALL);
- }
- mScoClients.remove(this);
- }
+ return true;
}
//-----------------------------------------------------
@@ -982,49 +832,6 @@
}
}
-
- @GuardedBy("BtHelper.this")
- private ScoClient getScoClient(IBinder cb, boolean create) {
- for (ScoClient existingClient : mScoClients) {
- if (existingClient.getBinder() == cb) {
- return existingClient;
- }
- }
- if (create) {
- ScoClient newClient = new ScoClient(cb);
- newClient.registerDeathRecipient();
- mScoClients.add(newClient);
- return newClient;
- }
- return null;
- }
-
- @GuardedBy("BtHelper.this")
- private ScoClient getScoClientForPid(int pid) {
- for (ScoClient cl : mScoClients) {
- if (cl.getPid() == pid) {
- return cl;
- }
- }
- return null;
- }
-
- // @GuardedBy("AudioDeviceBroker.mSetModeLock")
- //@GuardedBy("AudioDeviceBroker.mDeviceStateLock")
- @GuardedBy("BtHelper.this")
- private void clearAllScoClients(int exceptPid, boolean stopSco) {
- final ArrayList<ScoClient> clients = new ArrayList<ScoClient>();
- for (ScoClient cl : mScoClients) {
- if (cl.getPid() != exceptPid) {
- clients.add(cl);
- }
- }
- for (ScoClient cl : clients) {
- cl.remove(stopSco, true /*unregister*/);
- }
-
- }
-
private boolean getBluetoothHeadset() {
boolean result = false;
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
@@ -1070,10 +877,6 @@
pw.println(prefix + "mBluetoothHeadsetDevice: " + mBluetoothHeadsetDevice);
pw.println(prefix + "mScoAudioState: " + scoAudioStateToString(mScoAudioState));
pw.println(prefix + "mScoAudioMode: " + scoAudioModeToString(mScoAudioMode));
- pw.println(prefix + "Sco clients:");
- mScoClients.forEach((cl) -> {
- pw.println(" " + prefix + "pid: " + cl.getPid() + " cb: " + cl.getBinder()); });
-
pw.println("\n" + prefix + "mHearingAid: " + mHearingAid);
pw.println(prefix + "mA2dp: " + mA2dp);
pw.println(prefix + "mAvrcpAbsVolSupported: " + mAvrcpAbsVolSupported);
diff --git a/services/core/java/com/android/server/biometrics/HardwareAuthTokenUtils.java b/services/core/java/com/android/server/biometrics/HardwareAuthTokenUtils.java
new file mode 100644
index 0000000..eff4da3
--- /dev/null
+++ b/services/core/java/com/android/server/biometrics/HardwareAuthTokenUtils.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.biometrics;
+
+import static java.nio.ByteOrder.LITTLE_ENDIAN;
+
+import android.hardware.keymaster.HardwareAuthToken;
+import android.hardware.keymaster.Timestamp;
+
+import java.nio.ByteOrder;
+
+/**
+ * Utilities for converting between old and new HardwareAuthToken types. See
+ * {@link HardwareAuthToken}.
+ */
+public class HardwareAuthTokenUtils {
+ public static byte[] toByteArray(HardwareAuthToken hat) {
+ final byte[] array = new byte[69];
+
+ // Version, first byte. Used in hw_auth_token.h but not HardwareAuthToken
+ array[0] = 0;
+
+ // Challenge, 1:8.
+ writeLong(hat.challenge, array, 1 /* offset */);
+
+ // UserId, 9:16.
+ writeLong(hat.userId, array, 9 /* offset */);
+
+ // AuthenticatorId, 17:24.
+ writeLong(hat.authenticatorId, array, 17 /* offset */);
+
+ // AuthenticatorType, 25:28.
+ writeInt(flipIfNativelyLittle(hat.authenticatorType), array, 25 /* offset */);
+
+ // Timestamp, 29:36.
+ writeLong(flipIfNativelyLittle(hat.timestamp.milliSeconds), array, 29 /* offset */);
+
+ // MAC, 37:69. Byte array.
+ System.arraycopy(hat.mac, 0 /* srcPos */, array, 37 /* destPos */, hat.mac.length);
+
+ return array;
+ }
+
+ public static HardwareAuthToken toHardwareAuthToken(byte[] array) {
+ final HardwareAuthToken hardwareAuthToken = new HardwareAuthToken();
+
+ // First byte is version, which doesn't not exist in HardwareAuthToken anymore
+ // Next 8 bytes is the challenge.
+ hardwareAuthToken.challenge = getLong(array, 1 /* offset */);
+
+ // Next 8 bytes is the userId
+ hardwareAuthToken.userId = getLong(array, 9 /* offset */);
+
+ // Next 8 bytes is the authenticatorId.
+ hardwareAuthToken.authenticatorId = getLong(array, 17 /* offset */);
+
+ // Next 4 bytes is the authenticatorType.
+ hardwareAuthToken.authenticatorType = flipIfNativelyLittle(getInt(array, 25 /* offset */));
+
+ // Next 8 bytes is the timestamp.
+ final Timestamp timestamp = new Timestamp();
+ timestamp.milliSeconds = flipIfNativelyLittle(getLong(array, 29 /* offset */));
+ hardwareAuthToken.timestamp = timestamp;
+
+ // Last 32 bytes is the mac, 37:69
+ hardwareAuthToken.mac = new byte[32];
+ System.arraycopy(array, 37 /* srcPos */,
+ hardwareAuthToken.mac,
+ 0 /* destPos */,
+ 32 /* length */);
+
+ return hardwareAuthToken;
+ }
+
+ private static long flipIfNativelyLittle(long l) {
+ if (LITTLE_ENDIAN == ByteOrder.nativeOrder()) {
+ return Long.reverseBytes(l);
+ }
+ return l;
+ }
+
+ private static int flipIfNativelyLittle(int i) {
+ if (LITTLE_ENDIAN == ByteOrder.nativeOrder()) {
+ return Integer.reverseBytes(i);
+ }
+ return i;
+ }
+
+ private static void writeLong(long l, byte[] dest, int offset) {
+ dest[offset + 0] = (byte) l;
+ dest[offset + 1] = (byte) (l >> 8);
+ dest[offset + 2] = (byte) (l >> 16);
+ dest[offset + 3] = (byte) (l >> 24);
+ dest[offset + 4] = (byte) (l >> 32);
+ dest[offset + 5] = (byte) (l >> 40);
+ dest[offset + 6] = (byte) (l >> 48);
+ dest[offset + 7] = (byte) (l >> 56);
+ }
+
+ private static void writeInt(int i, byte[] dest, int offset) {
+ dest[offset + 0] = (byte) i;
+ dest[offset + 1] = (byte) (i >> 8);
+ dest[offset + 2] = (byte) (i >> 16);
+ dest[offset + 3] = (byte) (i >> 24);
+ }
+
+ private static long getLong(byte[] array, int offset) {
+ long result = 0;
+ // Lowest bit is LSB
+ for (int i = 0; i < 8; i++) {
+ result += (long) ((array[i + offset] & 0xffL) << (8 * i));
+ }
+ return result;
+ }
+
+ private static int getInt(byte[] array, int offset) {
+ int result = 0;
+ // Lowest bit is LSB
+ for (int i = 0; i < 4; i++) {
+ result += (int) (((int) array[i + offset] & 0xff) << (8 * i));
+ }
+ return result;
+ }
+}
diff --git a/services/core/java/com/android/server/biometrics/sensors/ClientMonitor.java b/services/core/java/com/android/server/biometrics/sensors/ClientMonitor.java
index 3c9dddd..0dee816 100644
--- a/services/core/java/com/android/server/biometrics/sensors/ClientMonitor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/ClientMonitor.java
@@ -73,7 +73,7 @@
T getDaemon();
}
- private final int mSequentialId;
+ protected final int mSequentialId;
@NonNull private final Context mContext;
@NonNull protected final LazyDaemon<T> mLazyDaemon;
private final int mTargetUserId;
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
index d353994..105fcec 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
@@ -20,6 +20,7 @@
import static android.Manifest.permission.MANAGE_BIOMETRIC;
import static android.Manifest.permission.MANAGE_FINGERPRINT;
import static android.Manifest.permission.RESET_FINGERPRINT_LOCKOUT;
+import static android.Manifest.permission.TEST_BIOMETRIC;
import static android.Manifest.permission.USE_BIOMETRIC;
import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL;
import static android.Manifest.permission.USE_FINGERPRINT;
@@ -32,6 +33,10 @@
import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.IBiometricSensorReceiver;
import android.hardware.biometrics.IBiometricServiceLockoutResetCallback;
+import android.hardware.biometrics.fingerprint.IFingerprint;
+import android.hardware.biometrics.fingerprint.SensorProps;
+import android.hardware.biometrics.ITestService;
+import android.hardware.biometrics.SensorPropertiesInternal;
import android.hardware.fingerprint.Fingerprint;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.hardware.fingerprint.IFingerprintClientActiveCallback;
@@ -40,9 +45,12 @@
import android.hardware.fingerprint.IUdfpsOverlayController;
import android.os.Binder;
import android.os.Build;
+import android.os.Handler;
import android.os.IBinder;
import android.os.NativeHandle;
import android.os.Process;
+import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.EventLog;
@@ -53,11 +61,13 @@
import com.android.internal.R;
import com.android.internal.util.DumpUtils;
import com.android.internal.widget.LockPatternUtils;
+import com.android.server.ServiceThread;
import com.android.server.SystemService;
import com.android.server.biometrics.Utils;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
import com.android.server.biometrics.sensors.LockoutResetDispatcher;
import com.android.server.biometrics.sensors.LockoutTracker;
+import com.android.server.biometrics.sensors.fingerprint.aidl.FingerprintProvider;
import com.android.server.biometrics.sensors.fingerprint.hidl.Fingerprint21;
import com.android.server.biometrics.sensors.fingerprint.hidl.Fingerprint21UdfpsMock;
@@ -81,11 +91,74 @@
private final GestureAvailabilityDispatcher mGestureAvailabilityDispatcher;
private final LockPatternUtils mLockPatternUtils;
@NonNull private List<ServiceProvider> mServiceProviders;
+ @Nullable private TestService mTestService;
+
+ private final class TestService extends ITestService.Stub {
+
+ @Override
+ public List<SensorPropertiesInternal> getSensorPropertiesInternal(
+ String opPackageName) {
+ Utils.checkPermission(getContext(), TEST_BIOMETRIC);
+ return null;
+ }
+
+ @Override
+ public void enableTestHal(int sensorId, boolean enableTestHal) {
+ Utils.checkPermission(getContext(), TEST_BIOMETRIC);
+ }
+
+ @Override
+ public void enrollStart(int sensorId, int userId) {
+ Utils.checkPermission(getContext(), TEST_BIOMETRIC);
+ }
+
+ @Override
+ public void enrollFinish(int sensorId, int userId) {
+ Utils.checkPermission(getContext(), TEST_BIOMETRIC);
+ }
+
+ @Override
+ public void authenticateSuccess(int sensorId, int userId) {
+ Utils.checkPermission(getContext(), TEST_BIOMETRIC);
+ }
+
+ @Override
+ public void authenticateReject(int sensorId, int userId) {
+ Utils.checkPermission(getContext(), TEST_BIOMETRIC);
+ }
+
+ @Override
+ public void notifyAcquired(int sensorId, int userId) {
+ Utils.checkPermission(getContext(), TEST_BIOMETRIC);
+ }
+
+ @Override
+ public void notifyError(int sensorId, int userId) {
+ Utils.checkPermission(getContext(), TEST_BIOMETRIC);
+ }
+
+ @Override
+ public void internalCleanup(int sensorId, int userId) {
+ Utils.checkPermission(getContext(), TEST_BIOMETRIC);
+ }
+ }
/**
* Receives the incoming binder calls from FingerprintManager.
*/
private final class FingerprintServiceWrapper extends IFingerprintService.Stub {
+ @Override
+ public ITestService getTestService(String opPackageName) {
+ Utils.checkPermission(getContext(), TEST_BIOMETRIC);
+
+ synchronized (this) {
+ if (mTestService == null) {
+ mTestService = new TestService();
+ }
+ }
+ return mTestService;
+ }
+
@Override // Binder call
public List<FingerprintSensorPropertiesInternal> getSensorPropertiesInternal(
String opPackageName) {
@@ -506,7 +579,7 @@
}
@Override
- public void onFingerDown(int sensorId, int x, int y, float minor, float major) {
+ public void onPointerDown(int sensorId, int x, int y, float minor, float major) {
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
final ServiceProvider provider = getProviderForSensor(sensorId);
@@ -514,11 +587,11 @@
Slog.w(TAG, "No matching provider for onFingerDown, sensorId: " + sensorId);
return;
}
- provider.onFingerDown(sensorId, x, y, minor, major);
+ provider.onPointerDown(sensorId, x, y, minor, major);
}
@Override
- public void onFingerUp(int sensorId) {
+ public void onPointerUp(int sensorId) {
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
final ServiceProvider provider = getProviderForSensor(sensorId);
@@ -526,7 +599,7 @@
Slog.w(TAG, "No matching provider for onFingerUp, sensorId: " + sensorId);
return;
}
- provider.onFingerUp(sensorId);
+ provider.onPointerUp(sensorId);
}
@Override
@@ -546,6 +619,39 @@
mLockoutResetDispatcher = new LockoutResetDispatcher(context);
mLockPatternUtils = new LockPatternUtils(context);
mServiceProviders = new ArrayList<>();
+
+ initializeAidlHals();
+ }
+
+ private void initializeAidlHals() {
+ final String[] instances = ServiceManager.getDeclaredInstances(IFingerprint.DESCRIPTOR);
+ if (instances == null || instances.length == 0) {
+ return;
+ }
+
+ // If for some reason the HAL is not started before the system service, do not block
+ // the rest of system server. Put this on a background thread.
+ final ServiceThread thread = new ServiceThread(TAG, Process.THREAD_PRIORITY_BACKGROUND,
+ true /* allowIo */);
+ thread.start();
+ final Handler handler = new Handler(thread.getLooper());
+
+ handler.post(() -> {
+ for (String instance : instances) {
+ final String fqName = IFingerprint.DESCRIPTOR + "/" + instance;
+ final IFingerprint fp = IFingerprint.Stub.asInterface(
+ ServiceManager.waitForDeclaredService(fqName));
+ try {
+ final SensorProps[] props = fp.getSensorProps();
+ final FingerprintProvider provider =
+ new FingerprintProvider(getContext(), props, fqName,
+ mLockoutResetDispatcher, mGestureAvailabilityDispatcher);
+ mServiceProviders.add(provider);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Remote exception when initializing instance: " + fqName);
+ }
+ }
+ });
}
@Override
@@ -571,6 +677,7 @@
private Pair<Integer, ServiceProvider> getSingleProvider() {
final List<FingerprintSensorPropertiesInternal> properties = getSensorProperties();
if (properties.size() != 1) {
+ Slog.e(TAG, "Multiple sensors found: " + properties.size());
return null;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java
index d7338a0..1162c9c 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java
@@ -92,6 +92,8 @@
@NonNull IFingerprintServiceReceiver receiver, int fingerId, int userId,
@NonNull String opPackageName);
+ void scheduleInternalCleanup(int sensorId, int userId);
+
boolean isHardwareDetected(int sensorId);
void rename(int sensorId, int fingerId, int userId, @NonNull String name);
@@ -102,9 +104,9 @@
long getAuthenticatorId(int sensorId, int userId);
- void onFingerDown(int sensorId, int x, int y, float minor, float major);
+ void onPointerDown(int sensorId, int x, int y, float minor, float major);
- void onFingerUp(int sensorId);
+ void onPointerUp(int sensorId);
void setUdfpsOverlayController(@NonNull IUdfpsOverlayController controller);
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Udfps.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/Udfps.java
similarity index 85%
rename from services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Udfps.java
rename to services/core/java/com/android/server/biometrics/sensors/fingerprint/Udfps.java
index 74cae02..0bf107a 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Udfps.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/Udfps.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.biometrics.sensors.fingerprint.hidl;
+package com.android.server.biometrics.sensors.fingerprint;
/**
* Interface for under-display fingerprint sensors.
@@ -22,6 +22,6 @@
* finger position (e.g. enroll, authenticate) should implement this.
*/
public interface Udfps {
- void onFingerDown(int x, int y, float minor, float major);
- void onFingerUp();
+ void onPointerDown(int x, int y, float minor, float major);
+ void onPointerUp();
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/UdfpsHelper.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/UdfpsHelper.java
similarity index 89%
rename from services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/UdfpsHelper.java
rename to services/core/java/com/android/server/biometrics/sensors/fingerprint/UdfpsHelper.java
index 0f1d6b4..a2b871e 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/UdfpsHelper.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/UdfpsHelper.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.biometrics.sensors.fingerprint.hidl;
+package com.android.server.biometrics.sensors.fingerprint;
import android.annotation.Nullable;
import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint;
@@ -29,7 +29,7 @@
private static final String TAG = "UdfpsHelper";
- static void onFingerDown(IBiometricsFingerprint daemon, int x, int y, float minor,
+ public static void onFingerDown(IBiometricsFingerprint daemon, int x, int y, float minor,
float major) {
android.hardware.biometrics.fingerprint.V2_3.IBiometricsFingerprint extension =
android.hardware.biometrics.fingerprint.V2_3.IBiometricsFingerprint.castFrom(
@@ -46,7 +46,7 @@
}
}
- static void onFingerUp(IBiometricsFingerprint daemon) {
+ public static void onFingerUp(IBiometricsFingerprint daemon) {
android.hardware.biometrics.fingerprint.V2_3.IBiometricsFingerprint extension =
android.hardware.biometrics.fingerprint.V2_3.IBiometricsFingerprint.castFrom(
daemon);
@@ -62,7 +62,7 @@
}
}
- static void showUdfpsOverlay(int sensorId,
+ public static void showUdfpsOverlay(int sensorId,
@Nullable IUdfpsOverlayController udfpsOverlayController) {
if (udfpsOverlayController == null) {
return;
@@ -74,7 +74,7 @@
}
}
- static void hideUdfpsOverlay(int sensorId,
+ public static void hideUdfpsOverlay(int sensorId,
@Nullable IUdfpsOverlayController udfpsOverlayController) {
if (udfpsOverlayController == null) {
return;
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
new file mode 100644
index 0000000..33f5418
--- /dev/null
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.biometrics.sensors.fingerprint.aidl;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.hardware.biometrics.BiometricFaceConstants;
+import android.hardware.biometrics.BiometricFingerprintConstants;
+import android.hardware.biometrics.common.ICancellationSignal;
+import android.hardware.biometrics.fingerprint.ISession;
+import android.hardware.fingerprint.IUdfpsOverlayController;
+import android.hardware.keymaster.HardwareAuthToken;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Slog;
+
+import com.android.server.biometrics.HardwareAuthTokenUtils;
+import com.android.server.biometrics.sensors.BiometricUtils;
+import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
+import com.android.server.biometrics.sensors.EnrollClient;
+import com.android.server.biometrics.sensors.fingerprint.FingerprintUtils;
+import com.android.server.biometrics.sensors.fingerprint.Udfps;
+import com.android.server.biometrics.sensors.fingerprint.UdfpsHelper;
+
+public class FingerprintEnrollClient extends EnrollClient<ISession> implements Udfps {
+
+ private static final String TAG = "FingerprintEnrollClient";
+
+ @Nullable private final IUdfpsOverlayController mUdfpsOverlayController;
+ @Nullable private ICancellationSignal mCancellationSignal;
+ private final int mMaxTemplatesPerUser;
+
+ public FingerprintEnrollClient(@NonNull Context context,
+ @NonNull LazyDaemon<ISession> lazyDaemon, @NonNull IBinder token,
+ @NonNull ClientMonitorCallbackConverter listener, int userId,
+ @NonNull byte[] hardwareAuthToken, @NonNull String owner, @NonNull BiometricUtils utils,
+ int statsModality, int sensorId,
+ @Nullable IUdfpsOverlayController udfpsOvelayController, int maxTemplatesPerUser) {
+ super(context, lazyDaemon, token, listener, userId, hardwareAuthToken, owner, utils,
+ 0 /* timeoutSec */, statsModality, sensorId, true /* shouldVibrate */);
+ mUdfpsOverlayController = udfpsOvelayController;
+ mMaxTemplatesPerUser = maxTemplatesPerUser;
+ }
+
+ @Override
+ protected boolean hasReachedEnrollmentLimit() {
+ return FingerprintUtils.getInstance()
+ .getBiometricsForUser(getContext(), getTargetUserId()).size()
+ >= mMaxTemplatesPerUser;
+ }
+
+ @Override
+ protected void stopHalOperation() {
+ UdfpsHelper.hideUdfpsOverlay(getSensorId(), mUdfpsOverlayController);
+ if (mCancellationSignal != null) {
+ try {
+ mCancellationSignal.cancel();
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Remote exception when requesting cancel", e);
+ onError(BiometricFingerprintConstants.FINGERPRINT_ERROR_HW_UNAVAILABLE,
+ 0 /* vendorCode */);
+ mCallback.onClientFinished(this, false /* success */);
+ }
+ }
+ }
+
+ @Override
+ protected void startHalOperation() {
+ UdfpsHelper.showUdfpsOverlay(getSensorId(), mUdfpsOverlayController);
+ try {
+ getFreshDaemon().enroll(mSequentialId,
+ HardwareAuthTokenUtils.toHardwareAuthToken(mHardwareAuthToken));
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Remote exception when requesting enroll", e);
+ onError(BiometricFaceConstants.FACE_ERROR_UNABLE_TO_PROCESS, 0 /* vendorCode */);
+ mCallback.onClientFinished(this, false /* success */);
+ }
+ }
+
+ @Override
+ public void onPointerDown(int x, int y, float minor, float major) {
+ try {
+ getFreshDaemon().onPointerDown(0 /* pointerId */, x, y, minor, major);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Unable to send pointer down", e);
+ }
+ }
+
+ @Override
+ public void onPointerUp() {
+ try {
+ getFreshDaemon().onPointerUp(0 /* pointerId */);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Unable to send pointer up", e);
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintGenerateChallengeClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintGenerateChallengeClient.java
new file mode 100644
index 0000000..3a6b113
--- /dev/null
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintGenerateChallengeClient.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.biometrics.sensors.fingerprint.aidl;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.hardware.biometrics.fingerprint.IFingerprint;
+import android.hardware.biometrics.fingerprint.IGenerateChallengeCallback;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Slog;
+
+import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
+import com.android.server.biometrics.sensors.GenerateChallengeClient;
+
+/**
+ * Fingerprint-specific generateChallenge client for the {@link IFingerprint} AIDL HAL interface.
+ */
+public class FingerprintGenerateChallengeClient extends GenerateChallengeClient<IFingerprint> {
+ private static final String TAG = "FingerprintGenerateChallengeClient";
+ private static final int CHALLENGE_TIMEOUT_SEC = 600; // 10 minutes
+
+ private IGenerateChallengeCallback mGenerateChallengeCallback =
+ new IGenerateChallengeCallback.Stub() {
+ @Override
+ public void onChallengeGenerated(int sensorId, int userId, long challenge) {
+ try {
+ getListener().onChallengeGenerated(sensorId, challenge);
+ mCallback.onClientFinished(FingerprintGenerateChallengeClient.this,
+ true /* success */);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Unable to send challenge", e);
+ mCallback.onClientFinished(FingerprintGenerateChallengeClient.this,
+ false /* success */);
+ }
+ }
+ };
+
+ public FingerprintGenerateChallengeClient(@NonNull Context context,
+ @NonNull LazyDaemon<IFingerprint> lazyDaemon,
+ @NonNull IBinder token,
+ @NonNull ClientMonitorCallbackConverter listener,
+ @NonNull String owner, int sensorId) {
+ super(context, lazyDaemon, token, listener, owner, sensorId);
+ }
+
+ @Override
+ protected void startHalOperation() {
+ try {
+ getFreshDaemon().generateChallenge(getSensorId(), getTargetUserId(),
+ CHALLENGE_TIMEOUT_SEC,
+ mGenerateChallengeCallback);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Unable to generateChallenge", e);
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
new file mode 100644
index 0000000..44a23cf
--- /dev/null
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
@@ -0,0 +1,325 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.biometrics.sensors.fingerprint.aidl;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.content.Context;
+import android.hardware.biometrics.BiometricsProtoEnums;
+import android.hardware.biometrics.fingerprint.IFingerprint;
+import android.hardware.biometrics.fingerprint.SensorProps;
+import android.hardware.fingerprint.Fingerprint;
+import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
+import android.hardware.fingerprint.IFingerprintServiceReceiver;
+import android.hardware.fingerprint.IUdfpsOverlayController;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.view.Surface;
+
+import com.android.server.biometrics.sensors.ClientMonitor;
+import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
+import com.android.server.biometrics.sensors.LockoutResetDispatcher;
+import com.android.server.biometrics.sensors.fingerprint.FingerprintUtils;
+import com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher;
+import com.android.server.biometrics.sensors.fingerprint.ServiceProvider;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Provider for a single instance of the {@link IFingerprint} HAL.
+ */
+public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvider {
+
+ @NonNull private final Context mContext;
+ @NonNull private final String mHalInstanceName;
+ @NonNull private final SparseArray<Sensor> mSensors; // Map of sensors that this HAL supports
+ @NonNull private final ClientMonitor.LazyDaemon<IFingerprint> mLazyDaemon;
+ @NonNull private final Handler mHandler;
+
+ @Nullable private IUdfpsOverlayController mUdfpsOverlayController;
+
+ public FingerprintProvider(@NonNull Context context, @NonNull SensorProps[] props,
+ @NonNull String halInstanceName, @NonNull LockoutResetDispatcher lockoutResetDispatcher,
+ @NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher) {
+ mContext = context;
+ mHalInstanceName = halInstanceName;
+ mSensors = new SparseArray<>();
+ mLazyDaemon = this::getHalInstance;
+ mHandler = new Handler(Looper.getMainLooper());
+
+ for (SensorProps prop : props) {
+ final int sensorId = prop.commonProps.sensorId;
+
+ final FingerprintSensorPropertiesInternal internalProp =
+ new FingerprintSensorPropertiesInternal(prop.commonProps.sensorId,
+ prop.commonProps.sensorStrength,
+ prop.commonProps.maxEnrollmentsPerUser,
+ prop.sensorType,
+ true /* resetLockoutRequiresHardwareAuthToken */);
+ final Sensor sensor = new Sensor(getTag() + "/" + sensorId, mContext, mHandler,
+ internalProp, gestureAvailabilityDispatcher);
+
+ mSensors.put(sensorId, sensor);
+ Slog.d(getTag(), "Added: " + internalProp);
+ }
+ }
+
+ private String getTag() {
+ return "FingerprintProvider/" + mHalInstanceName;
+ }
+
+ @Nullable
+ private synchronized IFingerprint getHalInstance() {
+ final IFingerprint daemon = IFingerprint.Stub.asInterface(
+ ServiceManager.waitForDeclaredService(mHalInstanceName));
+ if (daemon == null) {
+ Slog.e(getTag(), "Unable to get daemon");
+ return null;
+ }
+
+ try {
+ daemon.asBinder().linkToDeath(this, 0 /* flags */);
+ } catch (RemoteException e) {
+ Slog.e(getTag(), "Unable to linkToDeath", e);
+ }
+
+ for (int i = 0; i < mSensors.size(); i++) {
+ final int sensorId = mSensors.keyAt(i);
+ scheduleLoadAuthenticatorIds(sensorId);
+ scheduleInternalCleanup(sensorId, ActivityManager.getCurrentUser());
+ }
+
+ return daemon;
+ }
+
+ private void scheduleForSensor(int sensorId, @NonNull ClientMonitor<?> client) {
+ if (!mSensors.contains(sensorId)) {
+ throw new IllegalStateException("Unable to schedule client: " + client
+ + " for sensor: " + sensorId);
+ }
+ mSensors.get(sensorId).getScheduler().scheduleClientMonitor(client);
+ }
+
+ private void scheduleForSensor(int sensorId, @NonNull ClientMonitor<?> client,
+ ClientMonitor.Callback callback) {
+ if (!mSensors.contains(sensorId)) {
+ throw new IllegalStateException("Unable to schedule client: " + client
+ + " for sensor: " + sensorId);
+ }
+ mSensors.get(sensorId).getScheduler().scheduleClientMonitor(client, callback);
+ }
+
+ private void scheduleCreateSessionWithoutHandler(@NonNull IFingerprint daemon, int sensorId,
+ int userId) throws RemoteException {
+ // Note that per IFingerprint createSession contract, this method will block until all
+ // existing operations are canceled/finished. However, also note that this is fine, since
+ // this method "withoutHandler" means it should only ever be invoked from the worker thread,
+ // so callers will never be blocked.
+ mSensors.get(sensorId).createNewSession(daemon, sensorId, userId);
+ }
+
+ private void scheduleLoadAuthenticatorIdsWithoutHandler(int sensorId) {
+
+ }
+
+ private void scheduleLoadAuthenticatorIds(int sensorId) {
+
+ }
+
+ @Override
+ public boolean containsSensor(int sensorId) {
+ return mSensors.contains(sensorId);
+ }
+
+ @NonNull
+ @Override
+ public List<FingerprintSensorPropertiesInternal> getSensorProperties() {
+ List<FingerprintSensorPropertiesInternal> props = new ArrayList<>();
+ for (int i = 0; i < mSensors.size(); i++) {
+ props.add(mSensors.valueAt(i).getSensorProperties());
+ }
+ return props;
+ }
+
+ @Override
+ public void scheduleResetLockout(int sensorId, int userId, @Nullable byte[] hardwareAuthToken) {
+
+ }
+
+ @Override
+ public void scheduleGenerateChallenge(int sensorId, @NonNull IBinder token,
+ @NonNull IFingerprintServiceReceiver receiver, String opPackageName) {
+ mHandler.post(() -> {
+ final FingerprintGenerateChallengeClient client =
+ new FingerprintGenerateChallengeClient(mContext, mLazyDaemon, token,
+ new ClientMonitorCallbackConverter(receiver), opPackageName, sensorId);
+ mSensors.get(sensorId).getScheduler().scheduleClientMonitor(client);
+ });
+ }
+
+ @Override
+ public void scheduleRevokeChallenge(int sensorId, @NonNull IBinder token,
+ @NonNull String opPackageName) {
+
+ }
+
+ @Override
+ public void scheduleEnroll(int sensorId, @NonNull IBinder token, byte[] hardwareAuthToken,
+ int userId, @NonNull IFingerprintServiceReceiver receiver,
+ @NonNull String opPackageName, @Nullable Surface surface) {
+ mHandler.post(() -> {
+ final IFingerprint daemon = getHalInstance();
+ if (daemon == null) {
+ Slog.e(getTag(), "Null daemon during enroll, sensorId: " + sensorId);
+ return;
+ }
+
+ try {
+ if (!mSensors.get(sensorId).hasSessionForUser(userId)) {
+ scheduleCreateSessionWithoutHandler(daemon, sensorId, userId);
+ }
+
+ final int maxTemplatesPerUser = mSensors.get(sensorId).getSensorProperties()
+ .maxEnrollmentsPerUser;
+ final FingerprintEnrollClient client = new FingerprintEnrollClient(mContext,
+ mSensors.get(sensorId).getLazySession(), token,
+ new ClientMonitorCallbackConverter(receiver), userId, hardwareAuthToken,
+ opPackageName, FingerprintUtils.getInstance(),
+ BiometricsProtoEnums.MODALITY_FINGERPRINT, sensorId,
+ mUdfpsOverlayController, maxTemplatesPerUser);
+ scheduleForSensor(sensorId, client, new ClientMonitor.Callback() {
+ @Override
+ public void onClientFinished(@NonNull ClientMonitor<?> clientMonitor,
+ boolean success) {
+ if (success) {
+ scheduleLoadAuthenticatorIdsWithoutHandler(sensorId);
+ }
+ }
+ });
+ } catch (RemoteException e) {
+ Slog.e(getTag(), "Remote exception when scheduling enroll", e);
+ }
+ });
+ }
+
+ @Override
+ public void cancelEnrollment(int sensorId, @NonNull IBinder token) {
+
+ }
+
+ @Override
+ public void scheduleFingerDetect(int sensorId, @NonNull IBinder token, int userId,
+ @NonNull ClientMonitorCallbackConverter callback, @NonNull String opPackageName,
+ @Nullable Surface surface, int statsClient) {
+
+ }
+
+ @Override
+ public void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
+ int userId, int cookie, @NonNull ClientMonitorCallbackConverter callback,
+ @NonNull String opPackageName, boolean restricted, int statsClient,
+ boolean isKeyguard) {
+
+ }
+
+ @Override
+ public void startPreparedClient(int sensorId, int cookie) {
+
+ }
+
+ @Override
+ public void cancelAuthentication(int sensorId, @NonNull IBinder token) {
+
+ }
+
+ @Override
+ public void scheduleRemove(int sensorId, @NonNull IBinder token,
+ @NonNull IFingerprintServiceReceiver receiver, int fingerId, int userId,
+ @NonNull String opPackageName) {
+
+ }
+
+ @Override
+ public void scheduleInternalCleanup(int userId, int sensorId) {
+
+ }
+
+ @Override
+ public boolean isHardwareDetected(int sensorId) {
+ return false;
+ }
+
+ @Override
+ public void rename(int sensorId, int fingerId, int userId, @NonNull String name) {
+
+ }
+
+ @NonNull
+ @Override
+ public List<Fingerprint> getEnrolledFingerprints(int sensorId, int userId) {
+ return new ArrayList<>();
+ }
+
+ @Override
+ public int getLockoutModeForUser(int sensorId, int userId) {
+ return 0;
+ }
+
+ @Override
+ public long getAuthenticatorId(int sensorId, int userId) {
+ return 0;
+ }
+
+ @Override
+ public void onPointerDown(int sensorId, int x, int y, float minor, float major) {
+
+ }
+
+ @Override
+ public void onPointerUp(int sensorId) {
+
+ }
+
+ @Override
+ public void setUdfpsOverlayController(@NonNull IUdfpsOverlayController controller) {
+ mUdfpsOverlayController = controller;
+ }
+
+ @Override
+ public void dumpProto(int sensorId, @NonNull FileDescriptor fd) {
+
+ }
+
+ @Override
+ public void dumpInternal(int sensorId, @NonNull PrintWriter pw) {
+
+ }
+
+ @Override
+ public void binderDied() {
+
+ }
+}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java
new file mode 100644
index 0000000..3c27f9c
--- /dev/null
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.biometrics.sensors.fingerprint.aidl;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.hardware.biometrics.fingerprint.Error;
+import android.hardware.biometrics.fingerprint.IFingerprint;
+import android.hardware.biometrics.fingerprint.ISession;
+import android.hardware.biometrics.fingerprint.ISessionCallback;
+import android.hardware.fingerprint.Fingerprint;
+import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
+import android.hardware.keymaster.HardwareAuthToken;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.util.Slog;
+
+import com.android.server.biometrics.HardwareAuthTokenUtils;
+import com.android.server.biometrics.Utils;
+import com.android.server.biometrics.sensors.AcquisitionClient;
+import com.android.server.biometrics.sensors.AuthenticationConsumer;
+import com.android.server.biometrics.sensors.BiometricScheduler;
+import com.android.server.biometrics.sensors.ClientMonitor;
+import com.android.server.biometrics.sensors.Interruptable;
+import com.android.server.biometrics.sensors.fingerprint.FingerprintUtils;
+import com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Maintains the state of a single sensor within an instance of the
+ * {@link android.hardware.biometrics.fingerprint.IFingerprint} HAL.
+ */
+class Sensor {
+ @NonNull private final String mTag;
+ @NonNull private final Context mContext;
+ @NonNull private final Handler mHandler;
+ @NonNull private final FingerprintSensorPropertiesInternal mSensorProperties;
+ @NonNull private final BiometricScheduler mScheduler;
+
+ @Nullable private Session mCurrentSession; // TODO: Death recipient
+ @NonNull private final ClientMonitor.LazyDaemon<ISession> mLazySession;
+
+ private static class Session {
+ @NonNull private final String mTag;
+ @NonNull private final ISession mSession;
+ private final int mUserId;
+ private final ISessionCallback mSessionCallback;
+
+ Session(@NonNull String tag, @NonNull ISession session, int userId,
+ @NonNull ISessionCallback sessionCallback) {
+ mTag = tag;
+ mSession = session;
+ mUserId = userId;
+ mSessionCallback = sessionCallback;
+ Slog.d(mTag, "New session created for user: " + userId);
+ }
+ }
+
+ Sensor(@NonNull String tag, @NonNull Context context, @NonNull Handler handler,
+ @NonNull FingerprintSensorPropertiesInternal sensorProperties,
+ @NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher) {
+ mTag = tag;
+ mContext = context;
+ mHandler = handler;
+ mSensorProperties = sensorProperties;
+ mScheduler = new BiometricScheduler(tag, gestureAvailabilityDispatcher);
+ mLazySession = () -> mCurrentSession != null ? mCurrentSession.mSession : null;
+ }
+
+ @NonNull ClientMonitor.LazyDaemon<ISession> getLazySession() {
+ return mLazySession;
+ }
+
+ @NonNull FingerprintSensorPropertiesInternal getSensorProperties() {
+ return mSensorProperties;
+ }
+
+ boolean hasSessionForUser(int userId) {
+ return mCurrentSession != null && mCurrentSession.mUserId == userId;
+ }
+
+ void createNewSession(@NonNull IFingerprint daemon, int sensorId, int userId)
+ throws RemoteException {
+ final ISessionCallback callback = new ISessionCallback.Stub() {
+ @Override
+ public void onStateChanged(int cookie, byte state) {
+
+ }
+
+ @Override
+ public void onAcquired(byte info, int vendorCode) {
+ mHandler.post(() -> {
+ final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ if (!(client instanceof AcquisitionClient)) {
+ Slog.e(mTag, "onAcquired for non-acquisition client: "
+ + Utils.getClientName(client));
+ return;
+ }
+
+ final AcquisitionClient<?> acquisitionClient = (AcquisitionClient<?>) client;
+ acquisitionClient.onAcquired(info, vendorCode);
+ });
+ }
+
+ @Override
+ public void onError(byte error, int vendorCode) {
+ mHandler.post(() -> {
+ final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ Slog.d(mTag, "onError"
+ + ", client: " + Utils.getClientName(client)
+ + ", error: " + error
+ + ", vendorCode: " + vendorCode);
+ if (!(client instanceof Interruptable)) {
+ Slog.e(mTag, "onError for non-error consumer: "
+ + Utils.getClientName(client));
+ return;
+ }
+
+ final Interruptable interruptable = (Interruptable) client;
+ interruptable.onError(error, vendorCode);
+
+ if (error == Error.HW_UNAVAILABLE) {
+ Slog.e(mTag, "Got ERROR_HW_UNAVAILABLE");
+ mCurrentSession = null;
+ }
+ });
+ }
+
+ @Override
+ public void onEnrollmentProgress(int enrollmentId, int remaining) {
+ mHandler.post(() -> {
+ final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ if (!(client instanceof FingerprintEnrollClient)) {
+ Slog.e(mTag, "onEnrollmentProgress for non-enroll client: "
+ + Utils.getClientName(client));
+ return;
+ }
+
+ final int currentUserId = client.getTargetUserId();
+ final CharSequence name = FingerprintUtils.getInstance()
+ .getUniqueName(mContext, currentUserId);
+ final Fingerprint fingerprint = new Fingerprint(name, enrollmentId, sensorId);
+
+ final FingerprintEnrollClient enrollClient = (FingerprintEnrollClient) client;
+ enrollClient.onEnrollResult(fingerprint, remaining);
+ });
+ }
+
+ @Override
+ public void onAuthenticationSucceeded(int enrollmentId, HardwareAuthToken hat) {
+ mHandler.post(() -> {
+ final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ if (!(client instanceof AuthenticationConsumer)) {
+ Slog.e(mTag, "onAuthenticationSucceeded for non-authentication consumer: "
+ + Utils.getClientName(client));
+ return;
+ }
+
+ final AuthenticationConsumer authenticationConsumer =
+ (AuthenticationConsumer) client;
+ final Fingerprint fp = new Fingerprint("", enrollmentId, sensorId);
+ final byte[] byteArray = HardwareAuthTokenUtils.toByteArray(hat);
+ final ArrayList<Byte> byteList = new ArrayList<>();
+ for (byte b : byteArray) {
+ byteList.add(b);
+ }
+
+ authenticationConsumer.onAuthenticated(fp, true /* authenticated */, byteList);
+ });
+ }
+
+ @Override
+ public void onAuthenticationFailed() {
+ mHandler.post(() -> {
+ final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ if (!(client instanceof AuthenticationConsumer)) {
+ Slog.e(mTag, "onAuthenticationFailed for non-authentication consumer: "
+ + Utils.getClientName(client));
+ return;
+ }
+
+ final AuthenticationConsumer authenticationConsumer =
+ (AuthenticationConsumer) client;
+ final Fingerprint fp = new Fingerprint("", 0 /* enrollmentId */, sensorId);
+ authenticationConsumer
+ .onAuthenticated(fp, false /* authenticated */, null /* hat */);
+ });
+ }
+
+ @Override
+ public void onLockoutTimed(long durationMillis) {
+
+ }
+
+ @Override
+ public void onLockoutPermanent() {
+
+ }
+
+ @Override
+ public void onLockoutCleared() {
+
+ }
+
+ @Override
+ public void onInteractionDetected() {
+
+ }
+
+ @Override
+ public void onEnrollmentsEnumerated(int[] enrollmentIds) {
+
+ }
+
+ @Override
+ public void onEnrollmentsRemoved(int[] enrollmentIds) {
+
+ }
+
+ @Override
+ public void onAuthenticatorIdRetrieved(long authenticatorId) {
+
+ }
+
+ @Override
+ public void onAuthenticatorIdInvalidated() {
+
+ }
+ };
+
+ final ISession newSession = daemon.createSession(sensorId, userId, callback);
+ mCurrentSession = new Session(mTag, newSession, userId, callback);
+ }
+
+ @NonNull BiometricScheduler getScheduler() {
+ return mScheduler;
+ }
+}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
index f890f57..8ce99f4 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
@@ -68,6 +68,7 @@
import com.android.server.biometrics.sensors.fingerprint.FingerprintUtils;
import com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher;
import com.android.server.biometrics.sensors.fingerprint.ServiceProvider;
+import com.android.server.biometrics.sensors.fingerprint.Udfps;
import org.json.JSONArray;
import org.json.JSONException;
@@ -245,7 +246,7 @@
mHandler.post(() -> {
final ClientMonitor<?> client = mScheduler.getCurrentClient();
Slog.d(TAG, "handleError"
- + ", client: " + (client != null ? client.getOwnerString() : null)
+ + ", client: " + Utils.getClientName(client)
+ ", error: " + error
+ ", vendorCode: " + vendorCode);
if (!(client instanceof Interruptable)) {
@@ -635,6 +636,11 @@
}
@Override
+ public void scheduleInternalCleanup(int userId, int sensorId) {
+ scheduleInternalCleanup(userId);
+ }
+
+ @Override
public boolean isHardwareDetected(int sensorId) {
final IBiometricsFingerprint daemon = getDaemon();
return daemon != null;
@@ -664,25 +670,25 @@
}
@Override
- public void onFingerDown(int sensorId, int x, int y, float minor, float major) {
+ public void onPointerDown(int sensorId, int x, int y, float minor, float major) {
final ClientMonitor<?> client = mScheduler.getCurrentClient();
if (!(client instanceof Udfps)) {
Slog.w(TAG, "onFingerDown received during client: " + client);
return;
}
final Udfps udfps = (Udfps) client;
- udfps.onFingerDown(x, y, minor, major);
+ udfps.onPointerDown(x, y, minor, major);
}
@Override
- public void onFingerUp(int sensorId) {
+ public void onPointerUp(int sensorId) {
final ClientMonitor<?> client = mScheduler.getCurrentClient();
if (!(client instanceof Udfps)) {
Slog.w(TAG, "onFingerDown received during client: " + client);
return;
}
final Udfps udfps = (Udfps) client;
- udfps.onFingerUp();
+ udfps.onPointerUp();
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java
index 5dda5a8..e4933e4 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java
@@ -461,7 +461,7 @@
}
@Override
- public void onFingerDown(int sensorId, int x, int y, float minor, float major) {
+ public void onPointerDown(int sensorId, int x, int y, float minor, float major) {
mHandler.post(() -> {
Slog.d(TAG, "onFingerDown");
final AuthenticationConsumer lastAuthenticatedConsumer =
@@ -508,7 +508,7 @@
}
@Override
- public void onFingerUp(int sensorId) {
+ public void onPointerUp(int sensorId) {
mHandler.post(() -> {
Slog.d(TAG, "onFingerUp");
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
index 0658f95..46605d1 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
@@ -33,6 +33,8 @@
import com.android.server.biometrics.sensors.AuthenticationClient;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
import com.android.server.biometrics.sensors.LockoutTracker;
+import com.android.server.biometrics.sensors.fingerprint.Udfps;
+import com.android.server.biometrics.sensors.fingerprint.UdfpsHelper;
import java.util.ArrayList;
@@ -138,12 +140,12 @@
}
@Override
- public void onFingerDown(int x, int y, float minor, float major) {
+ public void onPointerDown(int x, int y, float minor, float major) {
UdfpsHelper.onFingerDown(getFreshDaemon(), x, y, minor, major);
}
@Override
- public void onFingerUp() {
+ public void onPointerUp() {
UdfpsHelper.onFingerUp(getFreshDaemon());
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java
index cad2214..4747488 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java
@@ -32,6 +32,8 @@
import com.android.server.biometrics.sensors.AuthenticationConsumer;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
import com.android.server.biometrics.sensors.PerformanceTracker;
+import com.android.server.biometrics.sensors.fingerprint.Udfps;
+import com.android.server.biometrics.sensors.fingerprint.UdfpsHelper;
import java.util.ArrayList;
@@ -93,12 +95,12 @@
}
@Override
- public void onFingerDown(int x, int y, float minor, float major) {
+ public void onPointerDown(int x, int y, float minor, float major) {
UdfpsHelper.onFingerDown(getFreshDaemon(), x, y, minor, major);
}
@Override
- public void onFingerUp() {
+ public void onPointerUp() {
UdfpsHelper.onFingerUp(getFreshDaemon());
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java
index b1030bf..975ac3d 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java
@@ -30,6 +30,8 @@
import com.android.server.biometrics.sensors.BiometricUtils;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
import com.android.server.biometrics.sensors.EnrollClient;
+import com.android.server.biometrics.sensors.fingerprint.Udfps;
+import com.android.server.biometrics.sensors.fingerprint.UdfpsHelper;
/**
* Fingerprint-specific enroll client supporting the
@@ -97,12 +99,12 @@
}
@Override
- public void onFingerDown(int x, int y, float minor, float major) {
+ public void onPointerDown(int x, int y, float minor, float major) {
UdfpsHelper.onFingerDown(getFreshDaemon(), x, y, minor, major);
}
@Override
- public void onFingerUp() {
+ public void onPointerUp() {
UdfpsHelper.onFingerUp(getFreshDaemon());
}
}
diff --git a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
index 01fa9e7..8625a6f 100644
--- a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
+++ b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
@@ -47,7 +47,6 @@
import android.net.NetworkUtils;
import android.net.SocketKeepalive.InvalidSocketException;
import android.net.TcpKeepalivePacketData;
-import android.net.util.IpUtils;
import android.net.util.KeepaliveUtils;
import android.os.Binder;
import android.os.Handler;
@@ -63,6 +62,7 @@
import com.android.internal.R;
import com.android.internal.util.HexDump;
import com.android.internal.util.IndentingPrintWriter;
+import com.android.net.module.util.IpUtils;
import java.io.FileDescriptor;
import java.net.InetAddress;
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 09c01d7..1ed6b35 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -2152,7 +2152,11 @@
break;
}
- // Prepare arguments for mtpd.
+ // Prepare arguments for mtpd. MTU/MRU calculated conservatively. Only IPv4 supported
+ // because LegacyVpn.
+ // 1500 - 60 (Carrier-internal IPv6 + UDP + GTP) - 10 (PPP) - 16 (L2TP) - 8 (UDP)
+ // - 77 (IPsec w/ SHA-2 512, 256b trunc-len, AES-CBC) - 8 (UDP encap) - 20 (IPv4)
+ // - 28 (464xlat)
String[] mtpd = null;
switch (profile.type) {
case VpnProfile.TYPE_PPTP:
@@ -2160,7 +2164,7 @@
iface, "pptp", profile.server, "1723",
"name", profile.username, "password", profile.password,
"linkname", "vpn", "refuse-eap", "nodefaultroute",
- "usepeerdns", "idle", "1800", "mtu", "1400", "mru", "1400",
+ "usepeerdns", "idle", "1800", "mtu", "1270", "mru", "1270",
(profile.mppe ? "+mppe" : "nomppe"),
};
break;
@@ -2170,7 +2174,7 @@
iface, "l2tp", profile.server, "1701", profile.l2tpSecret,
"name", profile.username, "password", profile.password,
"linkname", "vpn", "refuse-eap", "nodefaultroute",
- "usepeerdns", "idle", "1800", "mtu", "1400", "mru", "1400",
+ "usepeerdns", "idle", "1800", "mtu", "1270", "mru", "1270",
};
break;
}
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index af62aeb..ca94efc 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -1768,7 +1768,9 @@
final int callingUid = Binder.getCallingUid();
final long token = Binder.clearCallingIdentity();
try {
- return mLogicalDisplayMapper.getDisplayIdsLocked(callingUid);
+ synchronized (mSyncRoot) {
+ return mLogicalDisplayMapper.getDisplayIdsLocked(callingUid);
+ }
} finally {
Binder.restoreCallingIdentity(token);
}
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 6536457..3f4ddea 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -2089,6 +2089,16 @@
}
}
+ // Native callback
+ private void notifyUntrustedTouch(String packageName) {
+ // TODO(b/169067926): Remove toast after gathering feedback on dogfood.
+ DisplayThread.getHandler().post(() ->
+ Toast.makeText(mContext,
+ "Touch obscured by " + packageName
+ + " will be blocked. Check go/s-untrusted-touches",
+ Toast.LENGTH_SHORT).show());
+ }
+
// Native callback.
private long notifyANR(InputApplicationHandle inputApplicationHandle, IBinder token,
String reason) {
diff --git a/services/core/java/com/android/server/location/LocationManagerService.java b/services/core/java/com/android/server/location/LocationManagerService.java
index f72fee6..cdb73d8 100644
--- a/services/core/java/com/android/server/location/LocationManagerService.java
+++ b/services/core/java/com/android/server/location/LocationManagerService.java
@@ -216,7 +216,7 @@
private final LocalService mLocalService;
private final GeofenceManager mGeofenceManager;
- @Nullable private volatile GnssManagerService mGnssManagerService = null;
+ private volatile @Nullable GnssManagerService mGnssManagerService = null;
private GeocoderProxy mGeocodeProvider;
@GuardedBy("mLock")
@@ -604,7 +604,8 @@
|| !request.getWorkSource().isEmpty();
if (usesSystemApi
&& isChangeEnabled(PREVENT_PENDING_INTENT_SYSTEM_API_USAGE, identity.getUid())) {
- throw new SecurityException("PendingIntent location requests may not use system APIs");
+ throw new SecurityException(
+ "PendingIntent location requests may not use system APIs: " + request);
}
request = validateLocationRequest(request, identity);
@@ -1091,19 +1092,6 @@
}
@Override
- @NonNull
- public List<LocationRequest> getTestProviderCurrentRequests(String provider) {
- mContext.enforceCallingOrSelfPermission(permission.READ_DEVICE_CONFIG, null);
-
- LocationProviderManager manager = getLocationProviderManager(provider);
- if (manager == null) {
- throw new IllegalArgumentException("provider doesn't exist: " + provider);
- }
-
- return manager.getMockProviderRequests();
- }
-
- @Override
public int handleShellCommand(ParcelFileDescriptor in, ParcelFileDescriptor out,
ParcelFileDescriptor err, String[] args) {
return new LocationShellCommand(this).exec(
diff --git a/services/core/java/com/android/server/location/LocationProviderManager.java b/services/core/java/com/android/server/location/LocationProviderManager.java
index 3b3c6f0..5206571 100644
--- a/services/core/java/com/android/server/location/LocationProviderManager.java
+++ b/services/core/java/com/android/server/location/LocationProviderManager.java
@@ -1391,16 +1391,6 @@
}
}
- public List<LocationRequest> getMockProviderRequests() {
- synchronized (mLock) {
- if (!mProvider.isMock()) {
- throw new IllegalArgumentException(mName + " provider is not a test provider");
- }
-
- return mProvider.getCurrentRequest().getLocationRequests();
- }
- }
-
@Nullable
public Location getLastLocation(CallerIdentity identity, @PermissionLevel int permissionLevel,
boolean ignoreLocationSettings) {
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index 74b7bd7..4040f41 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -833,6 +833,7 @@
public void onUserSwitched(int user) {
if (DEBUG) Slog.d(TAG, "onUserSwitched u=" + user);
+ unbindOtherUserServices(user);
rebindServices(true, user);
}
@@ -1219,6 +1220,27 @@
bindToServices(componentsToBind);
}
+ /**
+ * Called when user switched to unbind all services from other users.
+ */
+ @VisibleForTesting
+ void unbindOtherUserServices(int currentUser) {
+ final SparseArray<Set<ComponentName>> componentsToUnbind = new SparseArray<>();
+
+ synchronized (mMutex) {
+ final Set<ManagedServiceInfo> removableBoundServices = getRemovableConnectedServices();
+ for (ManagedServiceInfo info : removableBoundServices) {
+ if (info.userid != currentUser) {
+ Set<ComponentName> toUnbind =
+ componentsToUnbind.get(info.userid, new ArraySet<>());
+ toUnbind.add(info.component);
+ componentsToUnbind.put(info.userid, toUnbind);
+ }
+ }
+ }
+ unbindFromServices(componentsToUnbind);
+ }
+
protected void unbindFromServices(SparseArray<Set<ComponentName>> componentsToUnbind) {
for (int i = 0; i < componentsToUnbind.size(); i++) {
final int userId = componentsToUnbind.keyAt(i);
@@ -1264,7 +1286,8 @@
/**
* Version of registerService that takes the name of a service component to bind to.
*/
- private void registerService(final ComponentName name, final int userid) {
+ @VisibleForTesting
+ void registerService(final ComponentName name, final int userid) {
synchronized (mMutex) {
registerServiceLocked(name, userid);
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 67ef029..269bd20 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -60,6 +60,7 @@
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.media.AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY;
import static android.media.AudioAttributes.USAGE_NOTIFICATION_RINGTONE;
import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_CRITICAL;
import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_NORMAL;
@@ -139,6 +140,7 @@
import android.app.UriGrantsManager;
import android.app.admin.DevicePolicyManagerInternal;
import android.app.backup.BackupManager;
+import android.app.compat.CompatChanges;
import android.app.role.OnRoleHoldersChangedListener;
import android.app.role.RoleManager;
import android.app.usage.UsageEvents;
@@ -407,6 +409,15 @@
@EnabledAfter(targetSdkVersion = Build.VERSION_CODES.Q)
private static final long CHANGE_BACKGROUND_CUSTOM_TOAST_BLOCK = 128611929L;
+ /**
+ * Activity starts coming from broadcast receivers or services in response to notification and
+ * notification action clicks will be blocked for UX and performance reasons. Instead start the
+ * activity directly from the PendingIntent.
+ */
+ @ChangeId
+ @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.R)
+ private static final long NOTIFICATION_TRAMPOLINE_BLOCK = 167676448L;
+
private IActivityManager mAm;
private ActivityTaskManagerInternal mAtm;
private ActivityManager mActivityManager;
@@ -7138,8 +7149,15 @@
// so need to check the notification still valide for vibrate.
synchronized (mNotificationLock) {
if (mNotificationsByKey.get(record.getKey()) != null) {
+ // Vibrator checks the appops for the op package, not the caller,
+ // so we need to add the bypass dnd flag to be heard. it's ok to
+ // always add this flag here because we've already checked that we can
+ // bypass dnd
+ AudioAttributes.Builder aab =
+ new AudioAttributes.Builder(record.getAudioAttributes())
+ .setFlags(FLAG_BYPASS_INTERRUPTION_POLICY);
mVibrator.vibrate(record.getSbn().getUid(), record.getSbn().getOpPkg(),
- effect, "Notification (delayed)", record.getAudioAttributes());
+ effect, "Notification (delayed)", aab.build());
} else {
Slog.e(TAG, "No vibration for canceled notification : "
+ record.getKey());
@@ -10005,7 +10023,7 @@
* TODO(b/161957908): Remove dogfooder toast.
*/
private class NotificationTrampolineCallback implements BackgroundActivityStartCallback {
- private Set<String> mPackagesShown = new ArraySet<>();
+ private final Set<String> mPackagesShown = new ArraySet<>();
@Override
public IBinder getToken() {
@@ -10013,20 +10031,25 @@
}
@Override
- public void onExclusiveTokenActivityStart(String packageName) {
- Slog.w(TAG, "Indirect notification activity start from " + packageName);
- boolean isFirstOccurrence = mPackagesShown.add(packageName);
- if (!isFirstOccurrence) {
- return;
+ public boolean isActivityStartAllowed(int uid, String packageName) {
+ boolean block = CompatChanges.isChangeEnabled(NOTIFICATION_TRAMPOLINE_BLOCK, uid);
+ if (block || mPackagesShown.add(packageName)) {
+ mUiHandler.post(() ->
+ Toast.makeText(getUiContext(),
+ "Indirect activity start from "
+ + packageName + ". "
+ + "This will be blocked in S.\n"
+ + "See go/s-trampolines.",
+ Toast.LENGTH_LONG).show());
}
-
- mUiHandler.post(() ->
- Toast.makeText(getUiContext(),
- "Indirect activity start from "
- + packageName + ". "
- + "This will be blocked in S.\n"
- + "See go/s-trampolines.",
- Toast.LENGTH_LONG).show());
+ String message =
+ "Indirect notification activity start (trampoline) from " + packageName;
+ if (block) {
+ Slog.e(TAG, message + " blocked");
+ return false;
+ }
+ Slog.w(TAG, message + ", this should be avoided for performance reasons");
+ return true;
}
}
}
diff --git a/services/core/java/com/android/server/notification/NotificationUsageStats.java b/services/core/java/com/android/server/notification/NotificationUsageStats.java
index b42fe92..9e91875 100644
--- a/services/core/java/com/android/server/notification/NotificationUsageStats.java
+++ b/services/core/java/com/android/server/notification/NotificationUsageStats.java
@@ -77,7 +77,6 @@
private final Map<String, AggregatedStats> mStats = new HashMap<>();
private final ArrayDeque<AggregatedStats[]> mStatsArrays = new ArrayDeque<>();
private ArraySet<String> mStatExpiredkeys = new ArraySet<>();
- private final SQLiteLog mSQLiteLog;
private final Context mContext;
private final Handler mHandler;
private long mLastEmitTime;
@@ -85,7 +84,6 @@
public NotificationUsageStats(Context context) {
mContext = context;
mLastEmitTime = SystemClock.elapsedRealtime();
- mSQLiteLog = ENABLE_SQLITE_LOG ? new SQLiteLog(context) : null;
mHandler = new Handler(mContext.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
@@ -152,9 +150,6 @@
stats.numUndecoratedRemoteViews += (notification.hasUndecoratedRemoteView() ? 1 : 0);
}
releaseAggregatedStatsLocked(aggregatedStatsArray);
- if (ENABLE_SQLITE_LOG) {
- mSQLiteLog.logPosted(notification);
- }
}
/**
@@ -170,9 +165,6 @@
stats.countApiUse(notification);
}
releaseAggregatedStatsLocked(aggregatedStatsArray);
- if (ENABLE_SQLITE_LOG) {
- mSQLiteLog.logPosted(notification);
- }
}
/**
@@ -185,9 +177,6 @@
stats.numRemovedByApp++;
}
releaseAggregatedStatsLocked(aggregatedStatsArray);
- if (ENABLE_SQLITE_LOG) {
- mSQLiteLog.logRemoved(notification);
- }
}
/**
@@ -197,9 +186,6 @@
MetricsLogger.histogram(mContext, "note_dismiss_longevity",
(int) (System.currentTimeMillis() - notification.getRankingTimeMs()) / (60 * 1000));
notification.stats.onDismiss();
- if (ENABLE_SQLITE_LOG) {
- mSQLiteLog.logDismissed(notification);
- }
}
/**
@@ -209,9 +195,6 @@
MetricsLogger.histogram(mContext, "note_click_longevity",
(int) (System.currentTimeMillis() - notification.getRankingTimeMs()) / (60 * 1000));
notification.stats.onClick();
- if (ENABLE_SQLITE_LOG) {
- mSQLiteLog.logClicked(notification);
- }
}
public synchronized void registerPeopleAffinity(NotificationRecord notification, boolean valid,
@@ -328,21 +311,18 @@
// pass
}
}
- if (ENABLE_SQLITE_LOG) {
- try {
- dump.put("historical", mSQLiteLog.dumpJson(filter));
- } catch (JSONException e) {
- // pass
- }
- }
return dump;
}
public PulledStats remoteViewStats(long startMs, boolean aggregate) {
- if (ENABLE_SQLITE_LOG) {
- if (aggregate) {
- return mSQLiteLog.remoteViewAggStats(startMs);
+ if (ENABLE_AGGREGATED_IN_MEMORY_STATS) {
+ PulledStats stats = new PulledStats(startMs);
+ for (AggregatedStats as : mStats.values()) {
+ if (as.numUndecoratedRemoteViews > 0) {
+ stats.addUndecoratedPackage(as.key, as.mCreated);
+ }
}
+ return stats;
}
return null;
}
@@ -357,9 +337,6 @@
pw.println(indent + "mStatsArrays.size(): " + mStatsArrays.size());
pw.println(indent + "mStats.size(): " + mStats.size());
}
- if (ENABLE_SQLITE_LOG) {
- mSQLiteLog.dump(pw, indent, filter);
- }
}
public synchronized void emit() {
@@ -1046,353 +1023,4 @@
'}';
}
}
-
- private static class SQLiteLog {
- private static final String TAG = "NotificationSQLiteLog";
-
- // Message types passed to the background handler.
- private static final int MSG_POST = 1;
- private static final int MSG_CLICK = 2;
- private static final int MSG_REMOVE = 3;
- private static final int MSG_DISMISS = 4;
-
- private static final String DB_NAME = "notification_log.db";
- private static final int DB_VERSION = 7;
-
- /** Age in ms after which events are pruned from the DB. */
- private static final long HORIZON_MS = 7 * 24 * 60 * 60 * 1000L; // 1 week
- /** Delay between pruning the DB. Used to throttle pruning. */
- private static final long PRUNE_MIN_DELAY_MS = 6 * 60 * 60 * 1000L; // 6 hours
- /** Mininum number of writes between pruning the DB. Used to throttle pruning. */
- private static final long PRUNE_MIN_WRITES = 1024;
-
- // Table 'log'
- private static final String TAB_LOG = "log";
- private static final String COL_EVENT_USER_ID = "event_user_id";
- private static final String COL_EVENT_TYPE = "event_type";
- private static final String COL_EVENT_TIME = "event_time_ms";
- private static final String COL_KEY = "key";
- private static final String COL_PKG = "pkg";
- private static final String COL_NOTIFICATION_ID = "nid";
- private static final String COL_TAG = "tag";
- private static final String COL_WHEN_MS = "when_ms";
- private static final String COL_DEFAULTS = "defaults";
- private static final String COL_FLAGS = "flags";
- private static final String COL_IMPORTANCE_REQ = "importance_request";
- private static final String COL_IMPORTANCE_FINAL = "importance_final";
- private static final String COL_NOISY = "noisy";
- private static final String COL_MUTED = "muted";
- private static final String COL_DEMOTED = "demoted";
- private static final String COL_CATEGORY = "category";
- private static final String COL_ACTION_COUNT = "action_count";
- private static final String COL_POSTTIME_MS = "posttime_ms";
- private static final String COL_AIRTIME_MS = "airtime_ms";
- private static final String COL_FIRST_EXPANSIONTIME_MS = "first_expansion_time_ms";
- private static final String COL_AIRTIME_EXPANDED_MS = "expansion_airtime_ms";
- private static final String COL_EXPAND_COUNT = "expansion_count";
- private static final String COL_UNDECORATED = "undecorated";
-
-
- private static final int EVENT_TYPE_POST = 1;
- private static final int EVENT_TYPE_CLICK = 2;
- private static final int EVENT_TYPE_REMOVE = 3;
- private static final int EVENT_TYPE_DISMISS = 4;
-
- private static final int IDLE_CONNECTION_TIMEOUT_MS = 30000;
-
- private static long sLastPruneMs;
-
- private static long sNumWrites;
- private final SQLiteOpenHelper mHelper;
-
- private final Handler mWriteHandler;
- private static final long DAY_MS = 24 * 60 * 60 * 1000;
- private static final String STATS_QUERY = "SELECT " +
- COL_EVENT_USER_ID + ", " +
- COL_PKG + ", " +
- // Bucket by day by looking at 'floor((midnight - eventTimeMs) / dayMs)'
- "CAST(((%d - " + COL_EVENT_TIME + ") / " + DAY_MS + ") AS int) " +
- "AS day, " +
- "COUNT(*) AS cnt, " +
- "SUM(" + COL_MUTED + ") as muted, " +
- "SUM(" + COL_NOISY + ") as noisy, " +
- "SUM(" + COL_DEMOTED + ") as demoted, " +
- "SUM(" + COL_UNDECORATED + ") as undecorated " +
- "FROM " + TAB_LOG + " " +
- "WHERE " +
- COL_EVENT_TYPE + "=" + EVENT_TYPE_POST +
- " AND " + COL_EVENT_TIME + " > %d " +
- " GROUP BY " + COL_EVENT_USER_ID + ", day, " + COL_PKG;
- private static final String UNDECORATED_QUERY = "SELECT " +
- COL_PKG + ", " +
- "MAX(" + COL_EVENT_TIME + ") as max_time " +
- "FROM " + TAB_LOG + " " +
- "WHERE " + COL_UNDECORATED + "> 0 " +
- " AND " + COL_EVENT_TIME + " > %d " +
- "GROUP BY " + COL_PKG;
-
- public SQLiteLog(Context context) {
- HandlerThread backgroundThread = new HandlerThread("notification-sqlite-log",
- android.os.Process.THREAD_PRIORITY_BACKGROUND);
- backgroundThread.start();
- mWriteHandler = new Handler(backgroundThread.getLooper()) {
- @Override
- public void handleMessage(Message msg) {
- NotificationRecord r = (NotificationRecord) msg.obj;
- long nowMs = System.currentTimeMillis();
- switch (msg.what) {
- case MSG_POST:
- writeEvent(r.getSbn().getPostTime(), EVENT_TYPE_POST, r);
- break;
- case MSG_CLICK:
- writeEvent(nowMs, EVENT_TYPE_CLICK, r);
- break;
- case MSG_REMOVE:
- writeEvent(nowMs, EVENT_TYPE_REMOVE, r);
- break;
- case MSG_DISMISS:
- writeEvent(nowMs, EVENT_TYPE_DISMISS, r);
- break;
- default:
- Log.wtf(TAG, "Unknown message type: " + msg.what);
- break;
- }
- }
- };
- mHelper = new SQLiteOpenHelper(context, DB_NAME, null, DB_VERSION) {
- @Override
- public void onCreate(SQLiteDatabase db) {
- db.execSQL("CREATE TABLE " + TAB_LOG + " (" +
- "_id INTEGER PRIMARY KEY AUTOINCREMENT," +
- COL_EVENT_USER_ID + " INT," +
- COL_EVENT_TYPE + " INT," +
- COL_EVENT_TIME + " INT," +
- COL_KEY + " TEXT," +
- COL_PKG + " TEXT," +
- COL_NOTIFICATION_ID + " INT," +
- COL_TAG + " TEXT," +
- COL_WHEN_MS + " INT," +
- COL_DEFAULTS + " INT," +
- COL_FLAGS + " INT," +
- COL_IMPORTANCE_REQ + " INT," +
- COL_IMPORTANCE_FINAL + " INT," +
- COL_NOISY + " INT," +
- COL_MUTED + " INT," +
- COL_DEMOTED + " INT," +
- COL_CATEGORY + " TEXT," +
- COL_ACTION_COUNT + " INT," +
- COL_POSTTIME_MS + " INT," +
- COL_AIRTIME_MS + " INT," +
- COL_FIRST_EXPANSIONTIME_MS + " INT," +
- COL_AIRTIME_EXPANDED_MS + " INT," +
- COL_EXPAND_COUNT + " INT," +
- COL_UNDECORATED + " INT" +
- ")");
- }
-
- @Override
- public void onConfigure(SQLiteDatabase db) {
- // Memory optimization - close idle connections after 30s of inactivity
- setIdleConnectionTimeout(IDLE_CONNECTION_TIMEOUT_MS);
- }
-
- @Override
- public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
- if (oldVersion != newVersion) {
- db.execSQL("DROP TABLE IF EXISTS " + TAB_LOG);
- onCreate(db);
- }
- }
- };
- }
-
- public void logPosted(NotificationRecord notification) {
- mWriteHandler.sendMessage(mWriteHandler.obtainMessage(MSG_POST, notification));
- }
-
- public void logClicked(NotificationRecord notification) {
- mWriteHandler.sendMessage(mWriteHandler.obtainMessage(MSG_CLICK, notification));
- }
-
- public void logRemoved(NotificationRecord notification) {
- mWriteHandler.sendMessage(mWriteHandler.obtainMessage(MSG_REMOVE, notification));
- }
-
- public void logDismissed(NotificationRecord notification) {
- mWriteHandler.sendMessage(mWriteHandler.obtainMessage(MSG_DISMISS, notification));
- }
-
- private JSONArray jsonPostFrequencies(DumpFilter filter) throws JSONException {
- JSONArray frequencies = new JSONArray();
- SQLiteDatabase db = mHelper.getReadableDatabase();
- long midnight = getMidnightMs();
- String q = String.format(STATS_QUERY, midnight, filter.since);
- Cursor cursor = db.rawQuery(q, null);
- try {
- for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
- int userId = cursor.getInt(0);
- String pkg = cursor.getString(1);
- if (filter != null && !filter.matches(pkg)) continue;
- int day = cursor.getInt(2);
- int count = cursor.getInt(3);
- int muted = cursor.getInt(4);
- int noisy = cursor.getInt(5);
- int demoted = cursor.getInt(6);
- JSONObject row = new JSONObject();
- row.put("user_id", userId);
- row.put("package", pkg);
- row.put("day", day);
- row.put("count", count);
- row.put("noisy", noisy);
- row.put("muted", muted);
- row.put("demoted", demoted);
- frequencies.put(row);
- }
- } finally {
- cursor.close();
- }
- return frequencies;
- }
-
- public void printPostFrequencies(PrintWriter pw, String indent, DumpFilter filter) {
- SQLiteDatabase db = mHelper.getReadableDatabase();
- long midnight = getMidnightMs();
- String q = String.format(STATS_QUERY, midnight, filter.since);
- Cursor cursor = db.rawQuery(q, null);
- try {
- for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
- int userId = cursor.getInt(0);
- String pkg = cursor.getString(1);
- if (filter != null && !filter.matches(pkg)) continue;
- int day = cursor.getInt(2);
- int count = cursor.getInt(3);
- int muted = cursor.getInt(4);
- int noisy = cursor.getInt(5);
- int demoted = cursor.getInt(6);
- pw.println(indent + "post_frequency{user_id=" + userId + ",pkg=" + pkg +
- ",day=" + day + ",count=" + count + ",muted=" + muted + "/" + noisy +
- ",demoted=" + demoted + "}");
- }
- } finally {
- cursor.close();
- }
- }
-
- private long getMidnightMs() {
- GregorianCalendar midnight = new GregorianCalendar();
- midnight.set(midnight.get(Calendar.YEAR), midnight.get(Calendar.MONTH),
- midnight.get(Calendar.DATE), 23, 59, 59);
- return midnight.getTimeInMillis();
- }
-
- private void writeEvent(long eventTimeMs, int eventType, NotificationRecord r) {
- ContentValues cv = new ContentValues();
- cv.put(COL_EVENT_USER_ID, r.getSbn().getUser().getIdentifier());
- cv.put(COL_EVENT_TIME, eventTimeMs);
- cv.put(COL_EVENT_TYPE, eventType);
- putNotificationIdentifiers(r, cv);
- if (eventType == EVENT_TYPE_POST) {
- putNotificationDetails(r, cv);
- } else {
- putPosttimeVisibility(r, cv);
- }
- cv.put(COL_UNDECORATED, (r.hasUndecoratedRemoteView() ? 1 : 0));
- SQLiteDatabase db = mHelper.getWritableDatabase();
- if (db.insert(TAB_LOG, null, cv) < 0) {
- Log.wtf(TAG, "Error while trying to insert values: " + cv);
- }
- sNumWrites++;
- pruneIfNecessary(db);
- }
-
- private void pruneIfNecessary(SQLiteDatabase db) {
- // Prune if we haven't in a while.
- long nowMs = System.currentTimeMillis();
- if (sNumWrites > PRUNE_MIN_WRITES ||
- nowMs - sLastPruneMs > PRUNE_MIN_DELAY_MS) {
- sNumWrites = 0;
- sLastPruneMs = nowMs;
- long horizonStartMs = nowMs - HORIZON_MS;
- try {
- int deletedRows = db.delete(TAB_LOG, COL_EVENT_TIME + " < ?",
- new String[]{String.valueOf(horizonStartMs)});
- Log.d(TAG, "Pruned event entries: " + deletedRows);
- } catch (SQLiteFullException e) {
- Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage()));
- }
- }
- }
-
- private static void putNotificationIdentifiers(NotificationRecord r, ContentValues outCv) {
- outCv.put(COL_KEY, r.getSbn().getKey());
- outCv.put(COL_PKG, r.getSbn().getPackageName());
- }
-
- private static void putNotificationDetails(NotificationRecord r, ContentValues outCv) {
- outCv.put(COL_NOTIFICATION_ID, r.getSbn().getId());
- if (r.getSbn().getTag() != null) {
- outCv.put(COL_TAG, r.getSbn().getTag());
- }
- outCv.put(COL_WHEN_MS, r.getSbn().getPostTime());
- outCv.put(COL_FLAGS, r.getNotification().flags);
- final int before = r.stats.requestedImportance;
- final int after = r.getImportance();
- final boolean noisy = r.stats.isNoisy;
- outCv.put(COL_IMPORTANCE_REQ, before);
- outCv.put(COL_IMPORTANCE_FINAL, after);
- outCv.put(COL_DEMOTED, after < before ? 1 : 0);
- outCv.put(COL_NOISY, noisy);
- if (noisy && after < IMPORTANCE_HIGH) {
- outCv.put(COL_MUTED, 1);
- } else {
- outCv.put(COL_MUTED, 0);
- }
- if (r.getNotification().category != null) {
- outCv.put(COL_CATEGORY, r.getNotification().category);
- }
- outCv.put(COL_ACTION_COUNT, r.getNotification().actions != null ?
- r.getNotification().actions.length : 0);
- }
-
- private static void putPosttimeVisibility(NotificationRecord r, ContentValues outCv) {
- outCv.put(COL_POSTTIME_MS, r.stats.getCurrentPosttimeMs());
- outCv.put(COL_AIRTIME_MS, r.stats.getCurrentAirtimeMs());
- outCv.put(COL_EXPAND_COUNT, r.stats.userExpansionCount);
- outCv.put(COL_AIRTIME_EXPANDED_MS, r.stats.getCurrentAirtimeExpandedMs());
- outCv.put(COL_FIRST_EXPANSIONTIME_MS, r.stats.posttimeToFirstVisibleExpansionMs);
- }
-
- public void dump(PrintWriter pw, String indent, DumpFilter filter) {
- printPostFrequencies(pw, indent, filter);
- }
-
- public JSONObject dumpJson(DumpFilter filter) {
- JSONObject dump = new JSONObject();
- try {
- dump.put("post_frequency", jsonPostFrequencies(filter));
- dump.put("since", filter.since);
- dump.put("now", System.currentTimeMillis());
- } catch (JSONException e) {
- // pass
- }
- return dump;
- }
-
- public PulledStats remoteViewAggStats(long startMs) {
- PulledStats stats = new PulledStats(startMs);
- SQLiteDatabase db = mHelper.getReadableDatabase();
- String q = String.format(UNDECORATED_QUERY, startMs);
- Cursor cursor = db.rawQuery(q, null);
- try {
- for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
- String pkg = cursor.getString(0);
- long maxTimeMs = cursor.getLong(1);
- stats.addUndecoratedPackage(pkg, maxTimeMs);
- }
- } finally {
- cursor.close();
- }
- return stats;
- }
- }
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 1104d4e..2e1543b 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -746,9 +746,6 @@
synchronized (mSessions) {
mSessions.put(sessionId, session);
}
- if (params.isStaged) {
- mStagingManager.createSession(session);
- }
mCallbacks.notifySessionCreated(session.sessionId, session.userId);
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 37fa9a2e..649cafb 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -1602,13 +1602,6 @@
validateApkInstallLocked();
}
}
- }
-
- if (params.isStaged) {
- mStagingManager.checkNonOverlappingWithStagedSessions(this);
- }
-
- synchronized (mLock) {
if (mDestroyed) {
throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
"Session destroyed");
@@ -2311,7 +2304,7 @@
return (params.installFlags & PackageManager.INSTALL_APEX) != 0;
}
- private boolean sessionContains(Predicate<PackageInstallerSession> filter) {
+ boolean sessionContains(Predicate<PackageInstallerSession> filter) {
if (!isMultiPackage()) {
return filter.test(this);
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index e9f8729..9caa91b 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -2232,8 +2232,7 @@
// Send installed broadcasts if the package is not a static shared lib.
if (res.pkg.getStaticSharedLibName() == null) {
- mProcessLoggingHandler.invalidateProcessLoggingBaseApkHash(
- res.pkg.getBaseApkPath());
+ mProcessLoggingHandler.invalidateBaseApkHash(res.pkg.getBaseApkPath());
// Send added for users that see the package for the first time
// sendPackageAddedForNewUsers also deals with system apps
@@ -2497,13 +2496,6 @@
}
}
- for (int i = 0, size = filesToChecksum.size(); i < size; ++i) {
- final File file = filesToChecksum.get(i).second;
- if (!file.exists()) {
- throw new IllegalStateException("File not found: " + file.getPath());
- }
- }
-
final Certificate[] trustedCerts = (trustedInstallers != null) ? decodeCertificates(
trustedInstallers) : null;
@@ -25806,25 +25798,16 @@
* @hide
*/
@Override
- public void logAppProcessStartIfNeeded(String processName, int uid, String seinfo,
- String apkFile, int pid) {
+ public void logAppProcessStartIfNeeded(String packageName, String processName, int uid,
+ String seinfo, String apkFile, int pid) {
if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
return;
}
if (!SecurityLog.isLoggingEnabled()) {
return;
}
- Bundle data = new Bundle();
- data.putLong("startTimestamp", System.currentTimeMillis());
- data.putString("processName", processName);
- data.putInt("uid", uid);
- data.putString("seinfo", seinfo);
- data.putString("apkFile", apkFile);
- data.putInt("pid", pid);
- Message msg = mProcessLoggingHandler.obtainMessage(
- ProcessLoggingHandler.LOG_APP_PROCESS_START_MSG);
- msg.setData(data);
- mProcessLoggingHandler.sendMessage(msg);
+ mProcessLoggingHandler.logAppProcessStart(mContext, this, apkFile, packageName, processName,
+ uid, seinfo, pid);
}
public CompilerStats.PackageStats getCompilerPackageStats(String pkgName) {
diff --git a/services/core/java/com/android/server/pm/ProcessLoggingHandler.java b/services/core/java/com/android/server/pm/ProcessLoggingHandler.java
index c47dda4..7fb34951d 100644
--- a/services/core/java/com/android/server/pm/ProcessLoggingHandler.java
+++ b/services/core/java/com/android/server/pm/ProcessLoggingHandler.java
@@ -16,29 +16,47 @@
package com.android.server.pm;
+import static android.content.pm.PackageManager.EXTRA_CHECKSUMS;
+
import android.app.admin.SecurityLog;
+import android.content.Context;
+import android.content.IIntentReceiver;
+import android.content.IIntentSender;
import android.content.Intent;
+import android.content.IntentSender;
+import android.content.pm.ApkChecksum;
+import android.content.pm.Checksum;
+import android.content.pm.IPackageManager;
import android.os.Bundle;
import android.os.Handler;
+import android.os.IBinder;
import android.os.Message;
+import android.os.Parcelable;
+import android.os.RemoteException;
+import android.text.TextUtils;
+import android.util.ArrayMap;
+import android.util.Slog;
import com.android.internal.os.BackgroundThread;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.HashMap;
-import android.util.Slog;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
public final class ProcessLoggingHandler extends Handler {
-
private static final String TAG = "ProcessLoggingHandler";
- static final int LOG_APP_PROCESS_START_MSG = 1;
- static final int INVALIDATE_BASE_APK_HASH_MSG = 2;
- private final HashMap<String, String> mProcessLoggingBaseApkHashes = new HashMap();
+ private static final int LOG_APP_PROCESS_START_MSG = 1;
+
+ private static final int CHECKSUM_TYPE = Checksum.TYPE_WHOLE_SHA256;
+
+ static class LoggingInfo {
+ public String apkHash = null;
+ public List<Bundle> pendingLogEntries = new ArrayList<>();
+ }
+
+ // Apk path to logging info map.
+ private final ArrayMap<String, LoggingInfo> mLoggingInfo = new ArrayMap<>();
ProcessLoggingHandler() {
super(BackgroundThread.getHandler().getLooper());
@@ -49,64 +67,133 @@
switch (msg.what) {
case LOG_APP_PROCESS_START_MSG: {
Bundle bundle = msg.getData();
+ long startTimestamp = bundle.getLong("startTimestamp");
String processName = bundle.getString("processName");
int uid = bundle.getInt("uid");
String seinfo = bundle.getString("seinfo");
- String apkFile = bundle.getString("apkFile");
int pid = bundle.getInt("pid");
- long startTimestamp = bundle.getLong("startTimestamp");
- String apkHash = computeStringHashOfApk(apkFile);
+ String apkHash = bundle.getString("apkHash");
SecurityLog.writeEvent(SecurityLog.TAG_APP_PROCESS_START, processName,
startTimestamp, uid, pid, seinfo, apkHash);
break;
}
- case INVALIDATE_BASE_APK_HASH_MSG: {
- Bundle bundle = msg.getData();
- mProcessLoggingBaseApkHashes.remove(bundle.getString("apkFile"));
+ }
+ }
+
+ void logAppProcessStart(Context context, IPackageManager pms, String apkFile,
+ String packageName, String processName, int uid, String seinfo, int pid) {
+ Bundle data = new Bundle();
+ data.putLong("startTimestamp", System.currentTimeMillis());
+ data.putString("processName", processName);
+ data.putInt("uid", uid);
+ data.putString("seinfo", seinfo);
+ data.putInt("pid", pid);
+
+ if (apkFile == null) {
+ enqueueSecurityLogEvent(data, "No APK");
+ return;
+ }
+
+ // Check cached apk hash.
+ boolean requestChecksums;
+ final LoggingInfo loggingInfo;
+ synchronized (mLoggingInfo) {
+ LoggingInfo cached = mLoggingInfo.get(apkFile);
+ requestChecksums = cached == null;
+ if (requestChecksums) {
+ // Create a new pending cache entry.
+ cached = new LoggingInfo();
+ mLoggingInfo.put(apkFile, cached);
+ }
+ loggingInfo = cached;
+ }
+
+ synchronized (loggingInfo) {
+ // Still pending?
+ if (!TextUtils.isEmpty(loggingInfo.apkHash)) {
+ enqueueSecurityLogEvent(data, loggingInfo.apkHash);
+ return;
+ }
+
+ loggingInfo.pendingLogEntries.add(data);
+ }
+
+ if (!requestChecksums) {
+ return;
+ }
+
+ // Request base checksums when first added entry.
+ // Capturing local loggingInfo to still log even if hash was invalidated.
+ try {
+ pms.requestChecksums(packageName, false, 0, CHECKSUM_TYPE, null,
+ new IntentSender((IIntentSender) new IIntentSender.Stub() {
+ @Override
+ public void send(int code, Intent intent, String resolvedType,
+ IBinder allowlistToken, IIntentReceiver finishedReceiver,
+ String requiredPermission, Bundle options) {
+ processChecksums(loggingInfo, intent);
+ }
+ }), context.getUserId());
+ } catch (RemoteException e) {
+ Slog.e(TAG, "requestChecksums() failed", e);
+ processChecksums(loggingInfo, null);
+ }
+ }
+
+ void processChecksums(final LoggingInfo loggingInfo, Intent intent) {
+ Parcelable[] parcelables = intent.getParcelableArrayExtra(EXTRA_CHECKSUMS);
+ ApkChecksum[] checksums = Arrays.copyOf(parcelables, parcelables.length,
+ ApkChecksum[].class);
+
+ for (ApkChecksum checksum : checksums) {
+ if (checksum.getType() == CHECKSUM_TYPE) {
+ processChecksum(loggingInfo, checksum.getValue());
break;
}
}
}
- void invalidateProcessLoggingBaseApkHash(String apkPath) {
- Bundle data = new Bundle();
- data.putString("apkFile", apkPath);
- Message msg = obtainMessage(INVALIDATE_BASE_APK_HASH_MSG);
- msg.setData(data);
- sendMessage(msg);
- }
-
- private String computeStringHashOfApk(String apkFile) {
- if (apkFile == null) {
- return "No APK";
+ void processChecksum(final LoggingInfo loggingInfo, final byte[] hash) {
+ final String apkHash;
+ if (hash != null) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < hash.length; i++) {
+ sb.append(String.format("%02x", hash[i]));
+ }
+ apkHash = sb.toString();
+ } else {
+ apkHash = "Failed to count APK hash";
}
- String apkHash = mProcessLoggingBaseApkHashes.get(apkFile);
- if (apkHash == null) {
- try {
- byte[] hash = computeHashOfApkFile(apkFile);
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < hash.length; i++) {
- sb.append(String.format("%02x", hash[i]));
- }
- apkHash = sb.toString();
- mProcessLoggingBaseApkHashes.put(apkFile, apkHash);
- } catch (IOException | NoSuchAlgorithmException e) {
- Slog.w(TAG, "computeStringHashOfApk() failed", e);
+
+ List<Bundle> pendingLogEntries;
+ synchronized (loggingInfo) {
+ if (!TextUtils.isEmpty(loggingInfo.apkHash)) {
+ return;
+ }
+ loggingInfo.apkHash = apkHash;
+
+ pendingLogEntries = loggingInfo.pendingLogEntries;
+ loggingInfo.pendingLogEntries = null;
+ }
+
+ if (pendingLogEntries != null) {
+ for (Bundle data : pendingLogEntries) {
+ enqueueSecurityLogEvent(data, apkHash);
}
}
- return apkHash != null ? apkHash : "Failed to count APK hash";
}
- private byte[] computeHashOfApkFile(String packageArchiveLocation)
- throws IOException, NoSuchAlgorithmException {
- MessageDigest md = MessageDigest.getInstance("SHA-256");
- FileInputStream input = new FileInputStream(new File(packageArchiveLocation));
- byte[] buffer = new byte[65536];
- int size;
- while ((size = input.read(buffer)) > 0) {
- md.update(buffer, 0, size);
+ void enqueueSecurityLogEvent(Bundle data, String apkHash) {
+ data.putString("apkHash", apkHash);
+
+ Message msg = this.obtainMessage(LOG_APP_PROCESS_START_MSG);
+ msg.setData(data);
+ this.sendMessage(msg);
+ }
+
+ void invalidateBaseApkHash(String apkFile) {
+ synchronized (mLoggingInfo) {
+ mLoggingInfo.remove(apkFile);
}
- input.close();
- return md.digest();
}
}
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 2db72784..3bad3cb 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -709,6 +709,8 @@
}
void commitSession(@NonNull PackageInstallerSession session) {
+ // Store this parent session which will be used to check overlapping later
+ createSession(session);
mPreRebootVerificationHandler.startPreRebootVerification(session);
}
@@ -738,14 +740,16 @@
* </ul>
* @throws PackageManagerException if session fails the check
*/
- void checkNonOverlappingWithStagedSessions(@NonNull PackageInstallerSession session)
+ private void checkNonOverlappingWithStagedSessions(@NonNull PackageInstallerSession session)
throws PackageManagerException {
if (session.isMultiPackage()) {
// We cannot say a parent session overlaps until we process its children
return;
}
- if (session.getPackageName() == null) {
- throw new PackageManagerException(PackageManager.INSTALL_FAILED_INVALID_APK,
+
+ String packageName = session.getPackageName();
+ if (packageName == null) {
+ throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
"Cannot stage session " + session.sessionId + " with package name null");
}
@@ -757,40 +761,26 @@
synchronized (mStagedSessions) {
for (int i = 0; i < mStagedSessions.size(); i++) {
final PackageInstallerSession stagedSession = mStagedSessions.valueAt(i);
- if (!stagedSession.isCommitted() || stagedSession.isStagedAndInTerminalState()
+ if (stagedSession.hasParentSessionId() || !stagedSession.isCommitted()
+ || stagedSession.isStagedAndInTerminalState()
|| stagedSession.isDestroyed()) {
continue;
}
- if (stagedSession.isMultiPackage()) {
- // This active parent staged session is useless as it doesn't have a package
- // name and the session we are checking is not a parent session either.
- continue;
- }
- // Check if stagedSession has an active parent session or not
- if (stagedSession.hasParentSessionId()) {
- final int parentId = stagedSession.getParentSessionId();
- final PackageInstallerSession parentSession = mStagedSessions.get(parentId);
- if (parentSession == null || parentSession.isStagedAndInTerminalState()
- || parentSession.isDestroyed()) {
- // Parent session has been abandoned or terminated already
- continue;
- }
- }
- // From here on, stagedSession is a non-parent active staged session
+ // From here on, stagedSession is a parent active staged session
// Check if session is one of the active sessions
- if (session.sessionId == stagedSession.sessionId) {
+ if (getSessionIdForParentOrSelf(session) == stagedSession.sessionId) {
Slog.w(TAG, "Session " + session.sessionId + " is already staged");
continue;
}
// New session cannot have same package name as one of the active sessions
- if (session.getPackageName().equals(stagedSession.getPackageName())) {
+ if (stagedSession.sessionContains(s -> s.getPackageName().equals(packageName))) {
if (isRollback) {
// If the new session is a rollback, then it gets priority. The existing
// session is failed to unblock rollback.
- final PackageInstallerSession root = getParentSessionOrSelf(stagedSession);
+ final PackageInstallerSession root = stagedSession;
if (!ensureActiveApexSessionIsAborted(root)) {
Slog.e(TAG, "Failed to abort apex session " + root.sessionId);
// Safe to ignore active apex session abort failure since session
@@ -804,7 +794,7 @@
+ "blocking rollback session: " + session.sessionId);
} else {
throw new PackageManagerException(
- PackageManager.INSTALL_FAILED_OTHER_STAGED_SESSION_IN_PROGRESS,
+ SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
"Package: " + session.getPackageName() + " in session: "
+ session.sessionId + " has been staged already by session:"
+ " " + stagedSession.sessionId, null);
@@ -814,17 +804,16 @@
// Staging multiple root sessions is not allowed if device doesn't support
// checkpoint. If session and stagedSession do not have common ancestor, they are
// from two different root sessions.
- if (!supportsCheckpoint && getSessionIdForParentOrSelf(session)
- != getSessionIdForParentOrSelf(stagedSession)) {
+ if (!supportsCheckpoint) {
throw new PackageManagerException(
- PackageManager.INSTALL_FAILED_OTHER_STAGED_SESSION_IN_PROGRESS,
+ SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
"Cannot stage multiple sessions without checkpoint support", null);
}
}
}
}
- void createSession(@NonNull PackageInstallerSession sessionInfo) {
+ private void createSession(@NonNull PackageInstallerSession sessionInfo) {
synchronized (mStagedSessions) {
mStagedSessions.append(sessionInfo.sessionId, sessionInfo);
}
@@ -900,16 +889,15 @@
}
void restoreSession(@NonNull PackageInstallerSession session, boolean isDeviceUpgrading) {
- PackageInstallerSession sessionToResume = session;
- synchronized (mStagedSessions) {
- mStagedSessions.append(session.sessionId, session);
- if (session.hasParentSessionId()) {
- // Only parent sessions can be restored
- return;
- }
+ if (session.hasParentSessionId()) {
+ // Only parent sessions can be restored
+ return;
}
+ // Store this parent session which will be used to check overlapping later
+ createSession(session);
// The preconditions used during pre-reboot verification might have changed when device
// is upgrading. Updated staged sessions to activation failed before we resume the session.
+ PackageInstallerSession sessionToResume = session;
if (isDeviceUpgrading && !sessionToResume.isStagedAndInTerminalState()) {
sessionToResume.setStagedSessionFailed(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED,
"Build fingerprint has changed");
@@ -1160,6 +1148,19 @@
* See {@link PreRebootVerificationHandler} to see all nodes of pre reboot verification
*/
private void handlePreRebootVerification_Start(@NonNull PackageInstallerSession session) {
+ try {
+ if (session.isMultiPackage()) {
+ for (PackageInstallerSession s : session.getChildSessions()) {
+ checkNonOverlappingWithStagedSessions(s);
+ }
+ } else {
+ checkNonOverlappingWithStagedSessions(session);
+ }
+ } catch (PackageManagerException e) {
+ onPreRebootVerificationFailure(session, e.error, e.getMessage());
+ return;
+ }
+
int rollbackId = -1;
if ((session.params.installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0) {
// If rollback is enabled for this session, we call through to the RollbackManager
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 2ada613..3ec156f 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -4708,9 +4708,12 @@
final UserInfo user = users.get(i);
final boolean running = am.isUserRunning(user.id, 0);
final boolean current = user.id == currentUser;
+ final boolean hasParent = user.profileGroupId != user.id
+ && user.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID;
if (verbose) {
- pw.printf("%d: id=%d, name=%s, flags=%s%s%s%s%s%s\n", i, user.id, user.name,
+ pw.printf("%d: id=%d, name=%s, flags=%s%s%s%s%s%s%s\n", i, user.id, user.name,
UserInfo.flagsToString(user.flags),
+ hasParent ? " (parentId=" + user.profileGroupId + ")" : "",
running ? " (running)" : "",
user.partial ? " (partial)" : "",
user.preCreated ? " (pre-created)" : "",
@@ -4791,6 +4794,11 @@
pw.print(" "); pw.print(userInfo);
pw.print(" serialNo="); pw.print(userInfo.serialNumber);
pw.print(" isPrimary="); pw.print(userInfo.isPrimary());
+ if (userInfo.profileGroupId != userInfo.id
+ && userInfo.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID) {
+ pw.print(" parentId="); pw.print(userInfo.profileGroupId);
+ }
+
if (mRemovingUserIds.get(userId)) {
pw.print(" <removing> ");
}
diff --git a/services/core/java/com/android/server/pm/permission/BasePermission.java b/services/core/java/com/android/server/pm/permission/BasePermission.java
index eb06bf9..c086017 100644
--- a/services/core/java/com/android/server/pm/permission/BasePermission.java
+++ b/services/core/java/com/android/server/pm/permission/BasePermission.java
@@ -433,18 +433,6 @@
throw new SecurityException("No permission tree found for " + permName);
}
- public void enforceDeclaredUsedAndRuntimeOrDevelopment(AndroidPackage pkg,
- UidPermissionState uidState) {
- if (!uidState.hasPermissionState(name) && !pkg.getRequestedPermissions().contains(name)) {
- throw new SecurityException("Package " + pkg.getPackageName()
- + " has not requested permission " + name);
- }
- if (!isRuntime() && !isDevelopment()) {
- throw new SecurityException("Permission " + name + " requested by "
- + pkg.getPackageName() + " is not a changeable permission type");
- }
- }
-
private static BasePermission findPermissionTree(
Collection<BasePermission> permissionTrees, String permName) {
for (BasePermission bp : permissionTrees) {
diff --git a/services/core/java/com/android/server/pm/permission/DevicePermissionState.java b/services/core/java/com/android/server/pm/permission/DevicePermissionState.java
index b9456acf..18936dd 100644
--- a/services/core/java/com/android/server/pm/permission/DevicePermissionState.java
+++ b/services/core/java/com/android/server/pm/permission/DevicePermissionState.java
@@ -21,57 +21,38 @@
import android.annotation.UserIdInt;
import android.util.SparseArray;
-import com.android.internal.annotations.GuardedBy;
-
/**
* Permission state for this device.
*/
public final class DevicePermissionState {
- @GuardedBy("mLock")
- @NonNull
private final SparseArray<UserPermissionState> mUserStates = new SparseArray<>();
- @NonNull
- private final Object mLock;
-
- public DevicePermissionState(@NonNull Object lock) {
- mLock = lock;
- }
-
@Nullable
public UserPermissionState getUserState(@UserIdInt int userId) {
- synchronized (mLock) {
- return mUserStates.get(userId);
- }
+ return mUserStates.get(userId);
}
@NonNull
public UserPermissionState getOrCreateUserState(@UserIdInt int userId) {
- synchronized (mLock) {
- UserPermissionState userState = mUserStates.get(userId);
- if (userState == null) {
- userState = new UserPermissionState(mLock);
- mUserStates.put(userId, userState);
- }
- return userState;
+ UserPermissionState userState = mUserStates.get(userId);
+ if (userState == null) {
+ userState = new UserPermissionState();
+ mUserStates.put(userId, userState);
}
+ return userState;
}
public void removeUserState(@UserIdInt int userId) {
- synchronized (mLock) {
- mUserStates.delete(userId);
- }
+ mUserStates.delete(userId);
}
public int[] getUserIds() {
- synchronized (mLock) {
- final int userStatesSize = mUserStates.size();
- final int[] userIds = new int[userStatesSize];
- for (int i = 0; i < userStatesSize; i++) {
- final int userId = mUserStates.keyAt(i);
- userIds[i] = userId;
- }
- return userIds;
+ final int userStatesSize = mUserStates.size();
+ final int[] userIds = new int[userStatesSize];
+ for (int i = 0; i < userStatesSize; i++) {
+ final int userId = mUserStates.keyAt(i);
+ userIds[i] = userId;
}
+ return userIds;
}
}
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index d356565..25e1848 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -216,8 +216,9 @@
/** Internal connection to the user manager */
private final UserManagerInternal mUserManagerInt;
+ @GuardedBy("mLock")
@NonNull
- private final DevicePermissionState mState;
+ private final DevicePermissionState mState = new DevicePermissionState();
/** Permission controller: User space permission management */
private PermissionControllerManager mPermissionControllerManager;
@@ -386,7 +387,6 @@
mPackageManagerInt = LocalServices.getService(PackageManagerInternal.class);
mUserManagerInt = LocalServices.getService(UserManagerInternal.class);
mSettings = new PermissionSettings(mLock);
- mState = new DevicePermissionState(mLock);
mAppOpsManager = context.getSystemService(AppOpsManager.class);
mHandlerThread = new ServiceThread(TAG,
@@ -665,20 +665,23 @@
if (pkg == null) {
return 0;
}
+ if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
+ return 0;
+ }
+
synchronized (mLock) {
if (mSettings.getPermissionLocked(permName) == null) {
return 0;
}
+
+ final UidPermissionState uidState = getUidStateLocked(pkg, userId);
+ if (uidState == null) {
+ Slog.e(TAG, "Missing permissions state for " + packageName + " and user " + userId);
+ return 0;
+ }
+
+ return uidState.getPermissionFlags(permName);
}
- if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
- return 0;
- }
- final UidPermissionState uidState = getUidState(pkg, userId);
- if (uidState == null) {
- Slog.e(TAG, "Missing permissions state for " + packageName + " and user " + userId);
- return 0;
- }
- return uidState.getPermissionFlags(permName);
}
@Override
@@ -772,52 +775,52 @@
throw new IllegalArgumentException("Unknown package: " + packageName);
}
- final BasePermission bp;
- synchronized (mLock) {
- bp = mSettings.getPermissionLocked(permName);
+ boolean isRequested = false;
+ // Fast path, the current package has requested the permission.
+ if (pkg.getRequestedPermissions().contains(permName)) {
+ isRequested = true;
}
- if (bp == null) {
- throw new IllegalArgumentException("Unknown permission: " + permName);
- }
-
- if (bp.isInstallerExemptIgnored()) {
- flagValues &= ~FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
- }
-
- final UidPermissionState uidState = getUidState(pkg, userId);
- if (uidState == null) {
- Slog.e(TAG, "Missing permissions state for " + packageName + " and user " + userId);
- return;
- }
-
- final boolean hadState = uidState.getPermissionState(permName) != null;
- if (!hadState) {
- boolean isRequested = false;
- // Fast path, the current package has requested the permission.
- if (pkg.getRequestedPermissions().contains(permName)) {
- isRequested = true;
- }
- if (!isRequested) {
- // Slow path, go through all shared user packages.
- String[] sharedUserPackageNames =
- mPackageManagerInt.getSharedUserPackagesForPackage(packageName, userId);
- for (String sharedUserPackageName : sharedUserPackageNames) {
- AndroidPackage sharedUserPkg = mPackageManagerInt.getPackage(
- sharedUserPackageName);
- if (sharedUserPkg != null
- && sharedUserPkg.getRequestedPermissions().contains(permName)) {
- isRequested = true;
- break;
- }
+ if (!isRequested) {
+ // Slow path, go through all shared user packages.
+ String[] sharedUserPackageNames =
+ mPackageManagerInt.getSharedUserPackagesForPackage(packageName, userId);
+ for (String sharedUserPackageName : sharedUserPackageNames) {
+ AndroidPackage sharedUserPkg = mPackageManagerInt.getPackage(
+ sharedUserPackageName);
+ if (sharedUserPkg != null
+ && sharedUserPkg.getRequestedPermissions().contains(permName)) {
+ isRequested = true;
+ break;
}
}
- if (!isRequested) {
+ }
+
+ final BasePermission bp;
+ final boolean permissionUpdated;
+ synchronized (mLock) {
+ bp = mSettings.getPermissionLocked(permName);
+ if (bp == null) {
+ throw new IllegalArgumentException("Unknown permission: " + permName);
+ }
+
+ if (bp.isInstallerExemptIgnored()) {
+ flagValues &= ~FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
+ }
+
+ final UidPermissionState uidState = getUidStateLocked(pkg, userId);
+ if (uidState == null) {
+ Slog.e(TAG, "Missing permissions state for " + packageName + " and user " + userId);
+ return;
+ }
+
+ if (!uidState.hasPermissionState(permName) && !isRequested) {
Log.e(TAG, "Permission " + permName + " isn't requested by package " + packageName);
return;
}
+
+ permissionUpdated = uidState.updatePermissionFlags(bp, flagMask, flagValues);
}
- final boolean permissionUpdated =
- uidState.updatePermissionFlags(bp, flagMask, flagValues);
+
if (permissionUpdated && bp.isRuntime()) {
notifyRuntimePermissionStateChanged(packageName, userId);
}
@@ -861,14 +864,17 @@
final boolean[] changed = new boolean[1];
mPackageManagerInt.forEachPackage(pkg -> {
- final UidPermissionState uidState = getUidState(pkg, userId);
- if (uidState == null) {
- Slog.e(TAG, "Missing permissions state for " + pkg.getPackageName() + " and user "
- + userId);
- return;
+ synchronized (mLock) {
+ final UidPermissionState uidState = getUidStateLocked(pkg, userId);
+ if (uidState == null) {
+ Slog.e(TAG,
+ "Missing permissions state for " + pkg.getPackageName() + " and user "
+ + userId);
+ return;
+ }
+ changed[0] |= uidState.updatePermissionFlagsForAllPermissions(
+ effectiveFlagMask, effectiveFlagValues);
}
- changed[0] |= uidState.updatePermissionFlagsForAllPermissions(
- effectiveFlagMask, effectiveFlagValues);
mOnPermissionChangeListeners.onPermissionsChanged(pkg.getUid());
});
@@ -920,33 +926,37 @@
}
final int uid = UserHandle.getUid(userId, pkg.getUid());
- final UidPermissionState uidState = getUidState(pkg, userId);
- if (uidState == null) {
- Slog.e(TAG, "Missing permissions state for " + pkg.getPackageName() + " and user "
- + userId);
- return PackageManager.PERMISSION_DENIED;
- }
+ final boolean isInstantApp = mPackageManagerInt.getInstantAppPackageName(uid) != null;
- if (checkSinglePermissionInternal(uid, uidState, permissionName)) {
- return PackageManager.PERMISSION_GRANTED;
- }
+ synchronized (mLock) {
+ final UidPermissionState uidState = getUidStateLocked(pkg, userId);
+ if (uidState == null) {
+ Slog.e(TAG, "Missing permissions state for " + pkg.getPackageName() + " and user "
+ + userId);
+ return PackageManager.PERMISSION_DENIED;
+ }
- final String fullerPermissionName = FULLER_PERMISSION_MAP.get(permissionName);
- if (fullerPermissionName != null
- && checkSinglePermissionInternal(uid, uidState, fullerPermissionName)) {
- return PackageManager.PERMISSION_GRANTED;
+ if (checkSinglePermissionInternalLocked(uidState, permissionName, isInstantApp)) {
+ return PackageManager.PERMISSION_GRANTED;
+ }
+
+ final String fullerPermissionName = FULLER_PERMISSION_MAP.get(permissionName);
+ if (fullerPermissionName != null && checkSinglePermissionInternalLocked(uidState,
+ fullerPermissionName, isInstantApp)) {
+ return PackageManager.PERMISSION_GRANTED;
+ }
}
return PackageManager.PERMISSION_DENIED;
}
- private boolean checkSinglePermissionInternal(int uid,
- @NonNull UidPermissionState uidState, @NonNull String permissionName) {
+ private boolean checkSinglePermissionInternalLocked(@NonNull UidPermissionState uidState,
+ @NonNull String permissionName, boolean isInstantApp) {
if (!uidState.isPermissionGranted(permissionName)) {
return false;
}
- if (mPackageManagerInt.getInstantAppPackageName(uid) != null) {
+ if (isInstantApp) {
return mSettings.isPermissionInstant(permissionName);
}
@@ -994,24 +1004,25 @@
return checkPermissionInternal(pkg, false, permissionName, userId);
}
- if (checkSingleUidPermissionInternal(uid, permissionName)) {
- return PackageManager.PERMISSION_GRANTED;
- }
+ synchronized (mLock) {
+ if (checkSingleUidPermissionInternalLocked(uid, permissionName)) {
+ return PackageManager.PERMISSION_GRANTED;
+ }
- final String fullerPermissionName = FULLER_PERMISSION_MAP.get(permissionName);
- if (fullerPermissionName != null
- && checkSingleUidPermissionInternal(uid, fullerPermissionName)) {
- return PackageManager.PERMISSION_GRANTED;
+ final String fullerPermissionName = FULLER_PERMISSION_MAP.get(permissionName);
+ if (fullerPermissionName != null
+ && checkSingleUidPermissionInternalLocked(uid, fullerPermissionName)) {
+ return PackageManager.PERMISSION_GRANTED;
+ }
}
return PackageManager.PERMISSION_DENIED;
}
- private boolean checkSingleUidPermissionInternal(int uid, @NonNull String permissionName) {
- synchronized (mLock) {
- ArraySet<String> permissions = mSystemPermissions.get(uid);
- return permissions != null && permissions.contains(permissionName);
- }
+ private boolean checkSingleUidPermissionInternalLocked(int uid,
+ @NonNull String permissionName) {
+ ArraySet<String> permissions = mSystemPermissions.get(uid);
+ return permissions != null && permissions.contains(permissionName);
}
@Override
@@ -1137,42 +1148,45 @@
final long identity = Binder.clearCallingIdentity();
try {
- final UidPermissionState uidState = getUidState(pkg, userId);
- if (uidState == null) {
- Slog.e(TAG, "Missing permissions state for " + packageName + " and user " + userId);
- return null;
- }
-
- int queryFlags = 0;
- if ((flags & PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM) != 0) {
- queryFlags |= FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
- }
- if ((flags & PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE) != 0) {
- queryFlags |= FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
- }
- if ((flags & PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER) != 0) {
- queryFlags |= FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
- }
- if ((flags & PackageManager.FLAG_PERMISSION_ALLOWLIST_ROLE) != 0) {
- queryFlags |= FLAG_PERMISSION_RESTRICTION_ROLE_EXEMPT;
- }
-
- ArrayList<String> whitelistedPermissions = null;
-
- final int permissionCount = ArrayUtils.size(pkg.getRequestedPermissions());
- for (int i = 0; i < permissionCount; i++) {
- final String permissionName = pkg.getRequestedPermissions().get(i);
- final int currentFlags =
- uidState.getPermissionFlags(permissionName);
- if ((currentFlags & queryFlags) != 0) {
- if (whitelistedPermissions == null) {
- whitelistedPermissions = new ArrayList<>();
- }
- whitelistedPermissions.add(permissionName);
+ synchronized (mLock) {
+ final UidPermissionState uidState = getUidStateLocked(pkg, userId);
+ if (uidState == null) {
+ Slog.e(TAG, "Missing permissions state for " + packageName + " and user "
+ + userId);
+ return null;
}
- }
- return whitelistedPermissions;
+ int queryFlags = 0;
+ if ((flags & PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM) != 0) {
+ queryFlags |= FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
+ }
+ if ((flags & PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE) != 0) {
+ queryFlags |= FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
+ }
+ if ((flags & PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER) != 0) {
+ queryFlags |= FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
+ }
+ if ((flags & PackageManager.FLAG_PERMISSION_ALLOWLIST_ROLE) != 0) {
+ queryFlags |= FLAG_PERMISSION_RESTRICTION_ROLE_EXEMPT;
+ }
+
+ ArrayList<String> whitelistedPermissions = null;
+
+ final int permissionCount = ArrayUtils.size(pkg.getRequestedPermissions());
+ for (int i = 0; i < permissionCount; i++) {
+ final String permissionName = pkg.getRequestedPermissions().get(i);
+ final int currentFlags =
+ uidState.getPermissionFlags(permissionName);
+ if ((currentFlags & queryFlags) != 0) {
+ if (whitelistedPermissions == null) {
+ whitelistedPermissions = new ArrayList<>();
+ }
+ whitelistedPermissions.add(permissionName);
+ }
+ }
+
+ return whitelistedPermissions;
+ }
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -1437,12 +1451,15 @@
"grantRuntimePermission");
final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName);
- final PackageSetting ps = (PackageSetting) mPackageManagerInt.getPackageSetting(
- packageName);
+ final PackageSetting ps = mPackageManagerInt.getPackageSetting(packageName);
if (pkg == null || ps == null) {
Log.e(TAG, "Unknown package: " + packageName);
return;
}
+ if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
+ throw new IllegalArgumentException("Unknown package: " + packageName);
+ }
+
final BasePermission bp;
synchronized (mLock) {
bp = mSettings.getPermissionLocked(permName);
@@ -1450,46 +1467,17 @@
if (bp == null) {
throw new IllegalArgumentException("Unknown permission: " + permName);
}
- if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
- throw new IllegalArgumentException("Unknown package: " + packageName);
- }
- final UidPermissionState uidState = getUidState(pkg, userId);
- if (uidState == null) {
- Slog.e(TAG, "Missing permissions state for " + pkg.getPackageName() + " and user "
- + userId);
- return;
+ if (!(bp.isRuntime() || bp.isDevelopment())) {
+ throw new SecurityException("Permission " + permName + " requested by "
+ + pkg.getPackageName() + " is not a changeable permission type");
}
- bp.enforceDeclaredUsedAndRuntimeOrDevelopment(pkg, uidState);
-
// If a permission review is required for legacy apps we represent
// their permissions as always granted runtime ones since we need
// to keep the review required permission flag per user while an
// install permission's state is shared across all users.
- if (pkg.getTargetSdkVersion() < Build.VERSION_CODES.M
- && bp.isRuntime()) {
- return;
- }
-
- final int uid = UserHandle.getUid(userId, UserHandle.getAppId(pkg.getUid()));
-
- final int flags = uidState.getPermissionFlags(permName);
- if ((flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0) {
- Log.e(TAG, "Cannot grant system fixed permission "
- + permName + " for package " + packageName);
- return;
- }
- if (!overridePolicy && (flags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0) {
- Log.e(TAG, "Cannot grant policy fixed permission "
- + permName + " for package " + packageName);
- return;
- }
-
- if (bp.isHardRestricted()
- && (flags & PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT) == 0) {
- Log.e(TAG, "Cannot grant hard restricted non-exempt permission "
- + permName + " for package " + packageName);
+ if (pkg.getTargetSdkVersion() < Build.VERSION_CODES.M && bp.isRuntime()) {
return;
}
@@ -1501,36 +1489,61 @@
return;
}
- if (bp.isDevelopment()) {
- // Development permissions must be handled specially, since they are not
- // normal runtime permissions. For now they apply to all users.
- // TODO(zhanghai): We are breaking the behavior above by making all permission state
- // per-user. It isn't documented behavior and relatively rarely used anyway.
- if (uidState.grantPermission(bp)) {
- if (callback != null) {
- callback.onInstallPermissionGranted();
- }
+ synchronized (mLock) {
+ final UidPermissionState uidState = getUidStateLocked(pkg, userId);
+ if (uidState == null) {
+ Slog.e(TAG, "Missing permissions state for " + pkg.getPackageName() + " and user "
+ + userId);
+ return;
}
- return;
- }
- if (ps.getInstantApp(userId) && !bp.isInstant()) {
- throw new SecurityException("Cannot grant non-ephemeral permission"
- + permName + " for package " + packageName);
- }
+ if (!(uidState.hasPermissionState(permName)
+ || pkg.getRequestedPermissions().contains(permName))) {
+ throw new SecurityException("Package " + pkg.getPackageName()
+ + " has not requested permission " + permName);
+ }
- if (pkg.getTargetSdkVersion() < Build.VERSION_CODES.M) {
- Slog.w(TAG, "Cannot grant runtime permission to a legacy app");
- return;
- }
+ final int flags = uidState.getPermissionFlags(permName);
+ if ((flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0) {
+ Log.e(TAG, "Cannot grant system fixed permission "
+ + permName + " for package " + packageName);
+ return;
+ }
+ if (!overridePolicy && (flags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0) {
+ Log.e(TAG, "Cannot grant policy fixed permission "
+ + permName + " for package " + packageName);
+ return;
+ }
- if (!uidState.grantPermission(bp)) {
- return;
- }
+ if (bp.isHardRestricted()
+ && (flags & PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT) == 0) {
+ Log.e(TAG, "Cannot grant hard restricted non-exempt permission "
+ + permName + " for package " + packageName);
+ return;
+ }
- if (bp.hasGids()) {
- if (callback != null) {
- callback.onGidsChanged(UserHandle.getAppId(pkg.getUid()), userId);
+ if (bp.isDevelopment()) {
+ // Development permissions must be handled specially, since they are not
+ // normal runtime permissions. For now they apply to all users.
+ // TODO(zhanghai): We are breaking the behavior above by making all permission state
+ // per-user. It isn't documented behavior and relatively rarely used anyway.
+ if (!uidState.grantPermission(bp)) {
+ return;
+ }
+ } else {
+ if (ps.getInstantApp(userId) && !bp.isInstant()) {
+ throw new SecurityException("Cannot grant non-ephemeral permission" + permName
+ + " for package " + packageName);
+ }
+
+ if (pkg.getTargetSdkVersion() < Build.VERSION_CODES.M) {
+ Slog.w(TAG, "Cannot grant runtime permission to a legacy app");
+ return;
+ }
+
+ if (!uidState.grantPermission(bp)) {
+ return;
+ }
}
}
@@ -1538,8 +1551,16 @@
logPermission(MetricsEvent.ACTION_PERMISSION_GRANTED, permName, packageName);
}
+ final int uid = UserHandle.getUid(userId, UserHandle.getAppId(pkg.getUid()));
if (callback != null) {
- callback.onPermissionGranted(uid, userId);
+ if (bp.isDevelopment()) {
+ callback.onInstallPermissionGranted();
+ } else {
+ callback.onPermissionGranted(uid, userId);
+ }
+ if (bp.hasGids()) {
+ callback.onGidsChanged(UserHandle.getAppId(pkg.getUid()), userId);
+ }
}
if (bp.isRuntime()) {
@@ -1593,56 +1614,57 @@
if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
throw new IllegalArgumentException("Unknown package: " + packageName);
}
- final BasePermission bp = mSettings.getPermissionLocked(permName);
+ final BasePermission bp = mSettings.getPermission(permName);
if (bp == null) {
throw new IllegalArgumentException("Unknown permission: " + permName);
}
- final UidPermissionState uidState = getUidState(pkg, userId);
- if (uidState == null) {
- Slog.e(TAG, "Missing permissions state for " + pkg.getPackageName() + " and user "
- + userId);
- return;
+ if (!(bp.isRuntime() || bp.isDevelopment())) {
+ throw new SecurityException("Permission " + permName + " requested by "
+ + pkg.getPackageName() + " is not a changeable permission type");
}
- bp.enforceDeclaredUsedAndRuntimeOrDevelopment(pkg, uidState);
+ synchronized (mLock) {
+ final UidPermissionState uidState = getUidStateLocked(pkg, userId);
+ if (uidState == null) {
+ Slog.e(TAG, "Missing permissions state for " + pkg.getPackageName() + " and user "
+ + userId);
+ return;
+ }
- // If a permission review is required for legacy apps we represent
- // their permissions as always granted runtime ones since we need
- // to keep the review required permission flag per user while an
- // install permission's state is shared across all users.
- if (pkg.getTargetSdkVersion() < Build.VERSION_CODES.M
- && bp.isRuntime()) {
- return;
- }
+ if (!(uidState.hasPermissionState(permName)
+ || pkg.getRequestedPermissions().contains(permName))) {
+ throw new SecurityException("Package " + pkg.getPackageName()
+ + " has not requested permission " + permName);
+ }
- final int flags = uidState.getPermissionFlags(permName);
- // Only the system may revoke SYSTEM_FIXED permissions.
- if ((flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0
- && UserHandle.getCallingAppId() != Process.SYSTEM_UID) {
- throw new SecurityException("Non-System UID cannot revoke system fixed permission "
- + permName + " for package " + packageName);
- }
- if (!overridePolicy && (flags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0) {
- throw new SecurityException("Cannot revoke policy fixed permission "
- + permName + " for package " + packageName);
- }
+ // If a permission review is required for legacy apps we represent
+ // their permissions as always granted runtime ones since we need
+ // to keep the review required permission flag per user while an
+ // install permission's state is shared across all users.
+ if (pkg.getTargetSdkVersion() < Build.VERSION_CODES.M && bp.isRuntime()) {
+ return;
+ }
- if (bp.isDevelopment()) {
+ final int flags = uidState.getPermissionFlags(permName);
+ // Only the system may revoke SYSTEM_FIXED permissions.
+ if ((flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0
+ && UserHandle.getCallingAppId() != Process.SYSTEM_UID) {
+ throw new SecurityException("Non-System UID cannot revoke system fixed permission "
+ + permName + " for package " + packageName);
+ }
+ if (!overridePolicy && (flags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0) {
+ throw new SecurityException("Cannot revoke policy fixed permission "
+ + permName + " for package " + packageName);
+ }
+
// Development permissions must be handled specially, since they are not
// normal runtime permissions. For now they apply to all users.
// TODO(zhanghai): We are breaking the behavior above by making all permission state
// per-user. It isn't documented behavior and relatively rarely used anyway.
- if (uidState.revokePermission(bp)) {
- if (callback != null) {
- mDefaultPermissionCallback.onInstallPermissionRevoked();
- }
+ if (!uidState.revokePermission(bp)) {
+ return;
}
- return;
- }
-
- if (!uidState.revokePermission(bp)) {
- return;
}
if (bp.isRuntime()) {
@@ -1650,8 +1672,12 @@
}
if (callback != null) {
- callback.onPermissionRevoked(UserHandle.getUid(userId,
- UserHandle.getAppId(pkg.getUid())), userId, reason);
+ if (bp.isDevelopment()) {
+ mDefaultPermissionCallback.onInstallPermissionRevoked();
+ } else {
+ callback.onPermissionRevoked(UserHandle.getUid(userId,
+ UserHandle.getAppId(pkg.getUid())), userId, reason);
+ }
}
if (bp.isRuntime()) {
@@ -1686,7 +1712,6 @@
* @param pkg The package for which to reset.
* @param userId The device user for which to do a reset.
*/
- @GuardedBy("mLock")
private void resetRuntimePermissionsInternal(final AndroidPackage pkg,
final int userId) {
final String packageName = pkg.getPackageName();
@@ -2323,7 +2348,7 @@
// Assume by default that we did not install this permission into the system.
p.setFlags(p.getFlags() & ~PermissionInfo.FLAG_INSTALLED);
- synchronized (PermissionManagerService.this.mLock) {
+ synchronized (mLock) {
// Now that permission groups have a special meaning, we ignore permission
// groups for legacy apps to prevent unexpected behavior. In particular,
// permissions for one app being granted to someone just because they happen
@@ -2463,31 +2488,35 @@
if (ps == null) {
return Collections.emptySet();
}
- final UidPermissionState uidState = getUidState(ps, userId);
- if (uidState == null) {
- Slog.e(TAG, "Missing permissions state for " + packageName + " and user " + userId);
- return Collections.emptySet();
- }
- if (!ps.getInstantApp(userId)) {
- return uidState.getGrantedPermissions();
- } else {
- // Install permission state is shared among all users, but instant app state is
- // per-user, so we can only filter it here unless we make install permission state
- // per-user as well.
- final Set<String> instantPermissions = new ArraySet<>(uidState.getGrantedPermissions());
- instantPermissions.removeIf(permissionName -> {
- BasePermission permission = mSettings.getPermission(permissionName);
- if (permission == null) {
- return true;
- }
- if (!permission.isInstant()) {
- EventLog.writeEvent(0x534e4554, "140256621", UserHandle.getUid(userId,
- ps.getAppId()), permissionName);
- return true;
- }
- return false;
- });
- return instantPermissions;
+
+ synchronized (mLock) {
+ final UidPermissionState uidState = getUidStateLocked(ps, userId);
+ if (uidState == null) {
+ Slog.e(TAG, "Missing permissions state for " + packageName + " and user " + userId);
+ return Collections.emptySet();
+ }
+ if (!ps.getInstantApp(userId)) {
+ return uidState.getGrantedPermissions();
+ } else {
+ // Install permission state is shared among all users, but instant app state is
+ // per-user, so we can only filter it here unless we make install permission state
+ // per-user as well.
+ final Set<String> instantPermissions =
+ new ArraySet<>(uidState.getGrantedPermissions());
+ instantPermissions.removeIf(permissionName -> {
+ BasePermission permission = mSettings.getPermission(permissionName);
+ if (permission == null) {
+ return true;
+ }
+ if (!permission.isInstant()) {
+ EventLog.writeEvent(0x534e4554, "140256621", UserHandle.getUid(userId,
+ ps.getAppId()), permissionName);
+ return true;
+ }
+ return false;
+ });
+ return instantPermissions;
+ }
}
}
@@ -3546,13 +3575,15 @@
}
// Legacy apps have the permission and get user consent on launch.
- final UidPermissionState uidState = getUidState(pkg, userId);
- if (uidState == null) {
- Slog.e(TAG, "Missing permissions state for " + pkg.getPackageName() + " and user "
- + userId);
- return false;
+ synchronized (mLock) {
+ final UidPermissionState uidState = getUidStateLocked(pkg, userId);
+ if (uidState == null) {
+ Slog.e(TAG, "Missing permissions state for " + pkg.getPackageName() + " and user "
+ + userId);
+ return false;
+ }
+ return uidState.isPermissionReviewRequired();
}
- return uidState.isPermissionReviewRequired();
}
private void grantRequestedRuntimePermissions(AndroidPackage pkg, int[] userIds,
@@ -3565,13 +3596,6 @@
private void grantRequestedRuntimePermissionsForUser(AndroidPackage pkg, int userId,
String[] grantedPermissions, int callingUid, PermissionCallback callback) {
- final UidPermissionState uidState = getUidState(pkg, userId);
- if (uidState == null) {
- Slog.e(TAG, "Missing permissions state for " + pkg.getPackageName() + " and user "
- + userId);
- return;
- }
-
final int immutableFlags = PackageManager.FLAG_PERMISSION_SYSTEM_FIXED
| PackageManager.FLAG_PERMISSION_POLICY_FIXED;
@@ -3593,7 +3617,8 @@
&& (supportsRuntimePermissions || !bp.isRuntimeOnly())
&& (grantedPermissions == null
|| ArrayUtils.contains(grantedPermissions, permission))) {
- final int flags = uidState.getPermissionFlags(permission);
+ final int flags = getPermissionFlagsInternal(permission, pkg.getPackageName(),
+ callingUid, userId);
if (supportsRuntimePermissions) {
// Installer cannot change immutable permissions.
if ((flags & immutableFlags) == 0) {
@@ -3621,12 +3646,6 @@
for (int i = 0; i < userIds.length; i++) {
int userId = userIds[i];
- final UidPermissionState uidState = getUidState(pkg, userId);
- if (uidState == null) {
- Slog.e(TAG, "Missing permissions state for " + pkg.getPackageName() + " and user "
- + userId);
- continue;
- }
for (int j = 0; j < permissionCount; j++) {
final String permissionName = pkg.getRequestedPermissions().get(j);
@@ -3637,14 +3656,26 @@
continue;
}
- if (uidState.isPermissionGranted(permissionName)) {
+ final boolean isGranted;
+ synchronized (mLock) {
+ final UidPermissionState uidState = getUidStateLocked(pkg, userId);
+ if (uidState == null) {
+ Slog.e(TAG, "Missing permissions state for " + pkg.getPackageName()
+ + " and user " + userId);
+ continue;
+ }
+ isGranted = uidState.isPermissionGranted(permissionName);
+ }
+
+ if (isGranted) {
if (oldGrantedRestrictedPermissions.get(userId) == null) {
oldGrantedRestrictedPermissions.put(userId, new ArraySet<>());
}
oldGrantedRestrictedPermissions.get(userId).add(permissionName);
}
- final int oldFlags = uidState.getPermissionFlags(permissionName);
+ final int oldFlags = getPermissionFlagsInternal(permissionName,
+ pkg.getPackageName(), callingUid, userId);
int newFlags = oldFlags;
int mask = 0;
@@ -3708,7 +3739,6 @@
// as whitelisting trumps policy i.e. policy cannot grant a non
// grantable permission.
if ((oldFlags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0) {
- final boolean isGranted = uidState.isPermissionGranted(permissionName);
if (!isWhitelisted && isGranted) {
mask |= PackageManager.FLAG_PERMISSION_POLICY_FIXED;
newFlags &= ~PackageManager.FLAG_PERMISSION_POLICY_FIXED;
@@ -3742,15 +3772,19 @@
final int oldGrantedCount = oldPermsForUser.size();
for (int j = 0; j < oldGrantedCount; j++) {
- final String permission = oldPermsForUser.valueAt(j);
+ final String permissionName = oldPermsForUser.valueAt(j);
// Sometimes we create a new permission state instance during update.
- final UidPermissionState newUidState = getUidState(pkg, userId);
- if (newUidState == null) {
- Slog.e(TAG, "Missing permissions state for " + pkg.getPackageName()
- + " and user " + userId);
- continue;
+ final boolean isGranted;
+ synchronized (mLock) {
+ final UidPermissionState uidState = getUidStateLocked(pkg, userId);
+ if (uidState == null) {
+ Slog.e(TAG, "Missing permissions state for " + pkg.getPackageName()
+ + " and user " + userId);
+ continue;
+ }
+ isGranted = uidState.isPermissionGranted(permissionName);
}
- if (!newUidState.isPermissionGranted(permission)) {
+ if (!isGranted) {
callback.onPermissionRevoked(pkg.getUid(), userId, null);
break;
}
@@ -3799,13 +3833,6 @@
continue;
}
- UidPermissionState uidState = getUidState(deletedPs.pkg, userId);
- if (uidState == null) {
- Slog.e(TAG, "Missing permissions state for " + deletedPs.pkg.getPackageName()
- + " and user " + userId);
- continue;
- }
-
PackageSetting disabledPs = mPackageManagerInt.getDisabledSystemPackage(
deletedPs.pkg.getPackageName());
@@ -3824,10 +3851,19 @@
}
}
- // TODO(zhanghai): Why are we only killing the UID when GIDs changed, instead of any
- // permission change?
- if (uidState.removePermissionState(bp.name) && bp.hasGids()) {
- affectedUserId = userId;
+ synchronized (mLock) {
+ UidPermissionState uidState = getUidStateLocked(deletedPs.pkg, userId);
+ if (uidState == null) {
+ Slog.e(TAG, "Missing permissions state for " + deletedPs.pkg.getPackageName()
+ + " and user " + userId);
+ continue;
+ }
+
+ // TODO(zhanghai): Why are we only killing the UID when GIDs changed, instead of any
+ // permission change?
+ if (uidState.removePermissionState(bp.name) && bp.hasGids()) {
+ affectedUserId = userId;
+ }
}
}
@@ -4122,14 +4158,17 @@
} else {
mPackageManagerInt.forEachPackage(p -> {
final int[] userIds = mUserManagerInt.getUserIds();
- for (final int userId : userIds) {
- final UidPermissionState uidState = getUidState(p, userId);
- if (uidState == null) {
- Slog.e(TAG, "Missing permissions state for "
- + p.getPackageName() + " and user " + userId);
- return;
+ synchronized (mLock) {
+ for (final int userId : userIds) {
+ final UidPermissionState uidState = getUidStateLocked(p,
+ userId);
+ if (uidState == null) {
+ Slog.e(TAG, "Missing permissions state for "
+ + p.getPackageName() + " and user " + userId);
+ continue;
+ }
+ uidState.removePermissionState(bp.name);
}
- uidState.removePermissionState(bp.name);
}
});
}
@@ -4537,26 +4576,24 @@
}
@Nullable
- private UidPermissionState getUidState(@NonNull PackageSetting ps,
+ private UidPermissionState getUidStateLocked(@NonNull PackageSetting ps,
@UserIdInt int userId) {
- return getUidState(ps.getAppId(), userId);
+ return getUidStateLocked(ps.getAppId(), userId);
}
@Nullable
- private UidPermissionState getUidState(@NonNull AndroidPackage pkg,
+ private UidPermissionState getUidStateLocked(@NonNull AndroidPackage pkg,
@UserIdInt int userId) {
- return getUidState(pkg.getUid(), userId);
+ return getUidStateLocked(pkg.getUid(), userId);
}
@Nullable
- private UidPermissionState getUidState(int appId, @UserIdInt int userId) {
- synchronized (mLock) {
- final UserPermissionState userState = mState.getUserState(userId);
- if (userState == null) {
- return null;
- }
- return userState.getUidState(appId);
+ private UidPermissionState getUidStateLocked(@AppIdInt int appId, @UserIdInt int userId) {
+ final UserPermissionState userState = mState.getUserState(userId);
+ if (userState == null) {
+ return null;
}
+ return userState.getUidState(appId);
}
private void removeAppIdState(@AppIdInt int appId) {
@@ -4601,7 +4638,10 @@
}
private void writeStateToPackageSettings() {
- final int[] userIds = mState.getUserIds();
+ final int[] userIds;
+ synchronized (mLock) {
+ userIds = mState.getUserIds();
+ }
mPackageManagerInt.forEachPackageSetting(ps -> {
ps.setInstallPermissionsFixed(false);
final LegacyPermissionState legacyState = ps.getLegacyPermissionState();
@@ -4652,27 +4692,30 @@
@NonNull
private LegacyPermissionState getLegacyPermissionState(@AppIdInt int appId) {
final LegacyPermissionState legacyState = new LegacyPermissionState();
- final int[] userIds = mState.getUserIds();
- for (final int userId : userIds) {
- final UidPermissionState uidState = getUidState(appId, userId);
- if (uidState == null) {
- Slog.e(TAG, "Missing permissions state for app ID " + appId + " and user ID "
- + userId);
- continue;
- }
+ synchronized (mLock) {
+ final int[] userIds = mState.getUserIds();
+ for (final int userId : userIds) {
+ final UidPermissionState uidState = getUidStateLocked(appId, userId);
+ if (uidState == null) {
+ Slog.e(TAG, "Missing permissions state for app ID " + appId + " and user ID "
+ + userId);
+ continue;
+ }
- final List<PermissionState> permissionStates = uidState.getPermissionStates();
- final int permissionStatesSize = permissionStates.size();
- for (int i = 0; i < permissionStatesSize; i++) {
- final PermissionState permissionState = permissionStates.get(i);
+ final List<PermissionState> permissionStates = uidState.getPermissionStates();
+ final int permissionStatesSize = permissionStates.size();
+ for (int i = 0; i < permissionStatesSize; i++) {
+ final PermissionState permissionState = permissionStates.get(i);
- final LegacyPermissionState.PermissionState legacyPermissionState =
- new LegacyPermissionState.PermissionState(permissionState.getPermission(),
- permissionState.isGranted(), permissionState.getFlags());
- if (permissionState.isRuntime()) {
- legacyState.putRuntimePermissionState(legacyPermissionState, userId);
- } else if (userId == UserHandle.USER_SYSTEM) {
- legacyState.putInstallPermissionState(legacyPermissionState);
+ final LegacyPermissionState.PermissionState legacyPermissionState =
+ new LegacyPermissionState.PermissionState(
+ permissionState.getPermission(), permissionState.isGranted(),
+ permissionState.getFlags());
+ if (permissionState.isRuntime()) {
+ legacyState.putRuntimePermissionState(legacyPermissionState, userId);
+ } else if (userId == UserHandle.USER_SYSTEM) {
+ legacyState.putInstallPermissionState(legacyPermissionState);
+ }
}
}
}
@@ -4683,12 +4726,15 @@
private int[] getGidsForUid(int uid) {
final int appId = UserHandle.getAppId(uid);
final int userId = UserHandle.getUserId(uid);
- final UidPermissionState uidState = getUidState(appId, userId);
- if (uidState == null) {
- Slog.e(TAG, "Missing permissions state for app ID " + appId + " and user ID " + userId);
- return EMPTY_INT_ARRAY;
+ synchronized (mLock) {
+ final UidPermissionState uidState = getUidStateLocked(appId, userId);
+ if (uidState == null) {
+ Slog.e(TAG, "Missing permissions state for app ID " + appId + " and user ID "
+ + userId);
+ return EMPTY_INT_ARRAY;
+ }
+ return uidState.computeGids(mGlobalGids, userId);
}
- return uidState.computeGids(mGlobalGids, userId);
}
private class PermissionManagerServiceInternalImpl extends PermissionManagerServiceInternal {
diff --git a/services/core/java/com/android/server/pm/permission/UidPermissionState.java b/services/core/java/com/android/server/pm/permission/UidPermissionState.java
index 82ab954..38e8955 100644
--- a/services/core/java/com/android/server/pm/permission/UidPermissionState.java
+++ b/services/core/java/com/android/server/pm/permission/UidPermissionState.java
@@ -24,8 +24,6 @@
import android.util.ArraySet;
import android.util.IntArray;
-import com.android.internal.annotations.GuardedBy;
-
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -35,29 +33,23 @@
* Permission state for a UID.
*/
public final class UidPermissionState {
- @NonNull
- private final Object mLock = new Object();
-
private boolean mMissing;
- @GuardedBy("mLock")
@Nullable
private ArrayMap<String, PermissionState> mPermissions;
public UidPermissionState() {}
public UidPermissionState(@NonNull UidPermissionState other) {
- synchronized (mLock) {
- mMissing = other.mMissing;
+ mMissing = other.mMissing;
- if (other.mPermissions != null) {
- mPermissions = new ArrayMap<>();
- final int permissionsSize = other.mPermissions.size();
- for (int i = 0; i < permissionsSize; i++) {
- final String name = other.mPermissions.keyAt(i);
- final PermissionState permissionState = other.mPermissions.valueAt(i);
- mPermissions.put(name, new PermissionState(permissionState));
- }
+ if (other.mPermissions != null) {
+ mPermissions = new ArrayMap<>();
+ final int permissionsSize = other.mPermissions.size();
+ for (int i = 0; i < permissionsSize; i++) {
+ final String name = other.mPermissions.keyAt(i);
+ final PermissionState permissionState = other.mPermissions.valueAt(i);
+ mPermissions.put(name, new PermissionState(permissionState));
}
}
}
@@ -66,11 +58,9 @@
* Reset the internal state of this object.
*/
public void reset() {
- synchronized (mLock) {
- mMissing = false;
- mPermissions = null;
- invalidateCache();
- }
+ mMissing = false;
+ mPermissions = null;
+ invalidateCache();
}
/**
@@ -97,9 +87,7 @@
*/
@Deprecated
public boolean hasPermissionState(@NonNull String name) {
- synchronized (mLock) {
- return mPermissions != null && mPermissions.containsKey(name);
- }
+ return mPermissions != null && mPermissions.containsKey(name);
}
/**
@@ -109,19 +97,17 @@
*/
@Deprecated
public boolean hasPermissionState(@NonNull ArraySet<String> names) {
- synchronized (mLock) {
- if (mPermissions == null) {
- return false;
- }
- final int namesSize = names.size();
- for (int i = 0; i < namesSize; i++) {
- final String name = names.valueAt(i);
- if (mPermissions.containsKey(name)) {
- return true;
- }
- }
+ if (mPermissions == null) {
return false;
}
+ final int namesSize = names.size();
+ for (int i = 0; i < namesSize; i++) {
+ final String name = names.valueAt(i);
+ if (mPermissions.containsKey(name)) {
+ return true;
+ }
+ }
+ return false;
}
/**
@@ -132,28 +118,24 @@
*/
@Nullable
public PermissionState getPermissionState(@NonNull String name) {
- synchronized (mLock) {
- if (mPermissions == null) {
- return null;
- }
- return mPermissions.get(name);
+ if (mPermissions == null) {
+ return null;
}
+ return mPermissions.get(name);
}
@NonNull
private PermissionState getOrCreatePermissionState(@NonNull BasePermission permission) {
- synchronized (mLock) {
- if (mPermissions == null) {
- mPermissions = new ArrayMap<>();
- }
- final String name = permission.getName();
- PermissionState permissionState = mPermissions.get(name);
- if (permissionState == null) {
- permissionState = new PermissionState(permission);
- mPermissions.put(name, permissionState);
- }
- return permissionState;
+ if (mPermissions == null) {
+ mPermissions = new ArrayMap<>();
}
+ final String name = permission.getName();
+ PermissionState permissionState = mPermissions.get(name);
+ if (permissionState == null) {
+ permissionState = new PermissionState(permission);
+ mPermissions.put(name, permissionState);
+ }
+ return permissionState;
}
/**
@@ -163,12 +145,10 @@
*/
@NonNull
public List<PermissionState> getPermissionStates() {
- synchronized (mLock) {
- if (mPermissions == null) {
- return Collections.emptyList();
- }
- return new ArrayList<>(mPermissions.values());
+ if (mPermissions == null) {
+ return Collections.emptyList();
}
+ return new ArrayList<>(mPermissions.values());
}
/**
@@ -179,20 +159,18 @@
* @param flags the permission flags
*/
public void putPermissionState(@NonNull BasePermission permission, boolean granted, int flags) {
- synchronized (mLock) {
- final String name = permission.getName();
- if (mPermissions == null) {
- mPermissions = new ArrayMap<>();
- } else {
- mPermissions.remove(name);
- }
- final PermissionState permissionState = new PermissionState(permission);
- if (granted) {
- permissionState.grant();
- }
- permissionState.updateFlags(flags, flags);
- mPermissions.put(name, permissionState);
+ final String name = permission.getName();
+ if (mPermissions == null) {
+ mPermissions = new ArrayMap<>();
+ } else {
+ mPermissions.remove(name);
}
+ final PermissionState permissionState = new PermissionState(permission);
+ if (granted) {
+ permissionState.grant();
+ }
+ permissionState.updateFlags(flags, flags);
+ mPermissions.put(name, permissionState);
}
/**
@@ -202,16 +180,14 @@
* @return whether the permission state changed
*/
public boolean removePermissionState(@NonNull String name) {
- synchronized (mLock) {
- if (mPermissions == null) {
- return false;
- }
- boolean changed = mPermissions.remove(name) != null;
- if (changed && mPermissions.isEmpty()) {
- mPermissions = null;
- }
- return changed;
+ if (mPermissions == null) {
+ return false;
}
+ final boolean changed = mPermissions.remove(name) != null;
+ if (changed && mPermissions.isEmpty()) {
+ mPermissions = null;
+ }
+ return changed;
}
/**
@@ -232,22 +208,20 @@
*/
@NonNull
public Set<String> getGrantedPermissions() {
- synchronized (mLock) {
- if (mPermissions == null) {
- return Collections.emptySet();
- }
-
- Set<String> permissions = new ArraySet<>(mPermissions.size());
- final int permissionsSize = mPermissions.size();
- for (int i = 0; i < permissionsSize; i++) {
- PermissionState permissionState = mPermissions.valueAt(i);
-
- if (permissionState.isGranted()) {
- permissions.add(permissionState.getName());
- }
- }
- return permissions;
+ if (mPermissions == null) {
+ return Collections.emptySet();
}
+
+ final Set<String> permissions = new ArraySet<>(mPermissions.size());
+ final int permissionsSize = mPermissions.size();
+ for (int i = 0; i < permissionsSize; i++) {
+ final PermissionState permissionState = mPermissions.valueAt(i);
+
+ if (permissionState.isGranted()) {
+ permissions.add(permissionState.getName());
+ }
+ }
+ return permissions;
}
/**
@@ -257,7 +231,7 @@
* @return whether the permission grant state changed
*/
public boolean grantPermission(@NonNull BasePermission permission) {
- PermissionState permissionState = getOrCreatePermissionState(permission);
+ final PermissionState permissionState = getOrCreatePermissionState(permission);
return permissionState.grant();
}
@@ -319,37 +293,33 @@
if (flagMask == 0) {
return false;
}
- synchronized (mLock) {
- if (mPermissions == null) {
- return false;
- }
- boolean anyChanged = false;
- for (int i = mPermissions.size() - 1; i >= 0; i--) {
- final PermissionState permissionState = mPermissions.valueAt(i);
- final boolean changed = permissionState.updateFlags(flagMask, flagValues);
- if (changed && permissionState.isDefault()) {
- mPermissions.removeAt(i);
- }
- anyChanged |= changed;
- }
- return anyChanged;
+ if (mPermissions == null) {
+ return false;
}
+ boolean anyChanged = false;
+ for (int i = mPermissions.size() - 1; i >= 0; i--) {
+ final PermissionState permissionState = mPermissions.valueAt(i);
+ final boolean changed = permissionState.updateFlags(flagMask, flagValues);
+ if (changed && permissionState.isDefault()) {
+ mPermissions.removeAt(i);
+ }
+ anyChanged |= changed;
+ }
+ return anyChanged;
}
public boolean isPermissionReviewRequired() {
- synchronized (mLock) {
- if (mPermissions == null) {
- return false;
- }
- final int permissionsSize = mPermissions.size();
- for (int i = 0; i < permissionsSize; i++) {
- final PermissionState permission = mPermissions.valueAt(i);
- if ((permission.getFlags() & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) != 0) {
- return true;
- }
- }
+ if (mPermissions == null) {
return false;
}
+ final int permissionsSize = mPermissions.size();
+ for (int i = 0; i < permissionsSize; i++) {
+ final PermissionState permission = mPermissions.valueAt(i);
+ if ((permission.getFlags() & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) != 0) {
+ return true;
+ }
+ }
+ return false;
}
/**
@@ -360,24 +330,22 @@
*/
@NonNull
public int[] computeGids(@NonNull int[] globalGids, @UserIdInt int userId) {
- synchronized (mLock) {
- IntArray gids = IntArray.wrap(globalGids);
- if (mPermissions == null) {
- return gids.toArray();
- }
- final int permissionsSize = mPermissions.size();
- for (int i = 0; i < permissionsSize; i++) {
- PermissionState permissionState = mPermissions.valueAt(i);
- if (!permissionState.isGranted()) {
- continue;
- }
- final int[] permissionGids = permissionState.computeGids(userId);
- if (permissionGids.length != 0) {
- gids.addAll(permissionGids);
- }
- }
+ IntArray gids = IntArray.wrap(globalGids);
+ if (mPermissions == null) {
return gids.toArray();
}
+ final int permissionsSize = mPermissions.size();
+ for (int i = 0; i < permissionsSize; i++) {
+ PermissionState permissionState = mPermissions.valueAt(i);
+ if (!permissionState.isGranted()) {
+ continue;
+ }
+ final int[] permissionGids = permissionState.computeGids(userId);
+ if (permissionGids.length != 0) {
+ gids.addAll(permissionGids);
+ }
+ }
+ return gids.toArray();
}
static void invalidateCache() {
diff --git a/services/core/java/com/android/server/pm/permission/UserPermissionState.java b/services/core/java/com/android/server/pm/permission/UserPermissionState.java
index 7f55cb1..2c741cf 100644
--- a/services/core/java/com/android/server/pm/permission/UserPermissionState.java
+++ b/services/core/java/com/android/server/pm/permission/UserPermissionState.java
@@ -23,8 +23,6 @@
import android.util.ArraySet;
import android.util.SparseArray;
-import com.android.internal.annotations.GuardedBy;
-
/**
* Permission state for a user.
*/
@@ -33,71 +31,52 @@
* Whether the install permissions have been granted to a package, so that no install
* permissions should be added to it unless the package is upgraded.
*/
- @GuardedBy("mLock")
@NonNull
private final ArraySet<String> mInstallPermissionsFixed = new ArraySet<>();
/**
* Maps from app ID to {@link UidPermissionState}.
*/
- @GuardedBy("mLock")
@NonNull
private final SparseArray<UidPermissionState> mUidStates = new SparseArray<>();
- @NonNull
- private final Object mLock;
-
- public UserPermissionState(@NonNull Object lock) {
- mLock = lock;
- }
-
public boolean areInstallPermissionsFixed(@NonNull String packageName) {
- synchronized (mLock) {
- return mInstallPermissionsFixed.contains(packageName);
- }
+ return mInstallPermissionsFixed.contains(packageName);
}
public void setInstallPermissionsFixed(@NonNull String packageName, boolean fixed) {
- synchronized (mLock) {
- if (fixed) {
- mInstallPermissionsFixed.add(packageName);
- } else {
- mInstallPermissionsFixed.remove(packageName);
- }
+ if (fixed) {
+ mInstallPermissionsFixed.add(packageName);
+ } else {
+ mInstallPermissionsFixed.remove(packageName);
}
}
@Nullable
public UidPermissionState getUidState(@AppIdInt int appId) {
checkAppId(appId);
- synchronized (mLock) {
- return mUidStates.get(appId);
- }
+ return mUidStates.get(appId);
}
@NonNull
public UidPermissionState getOrCreateUidState(@AppIdInt int appId) {
checkAppId(appId);
- synchronized (mLock) {
- UidPermissionState uidState = mUidStates.get(appId);
- if (uidState == null) {
- uidState = new UidPermissionState();
- mUidStates.put(appId, uidState);
- }
- return uidState;
+ UidPermissionState uidState = mUidStates.get(appId);
+ if (uidState == null) {
+ uidState = new UidPermissionState();
+ mUidStates.put(appId, uidState);
}
+ return uidState;
}
public void removeUidState(@AppIdInt int appId) {
checkAppId(appId);
- synchronized (mLock) {
- mUidStates.delete(appId);
- }
+ mUidStates.delete(appId);
}
private void checkAppId(@AppIdInt int appId) {
if (UserHandle.getUserId(appId) != 0) {
- throw new IllegalArgumentException(appId + " is not an app ID");
+ throw new IllegalArgumentException("Invalid app ID " + appId);
}
}
}
diff --git a/services/core/java/com/android/server/power/batterysaver/TEST_MAPPING b/services/core/java/com/android/server/power/batterysaver/TEST_MAPPING
new file mode 100644
index 0000000..17dba7d
--- /dev/null
+++ b/services/core/java/com/android/server/power/batterysaver/TEST_MAPPING
@@ -0,0 +1,19 @@
+{
+ "presubmit": [
+ {
+ "name": "CtsLocationCoarseTestCases"
+ },
+ {
+ "name": "CtsLocationFineTestCases"
+ },
+ {
+ "name": "CtsLocationNoneTestCases"
+ },
+ {
+ "name": "FrameworksMockingServicesTests",
+ "options": [
+ {"include-filter": "com.android.server.location"}
+ ]
+ }
+ ]
+}
diff --git a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewarePermission.java b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewarePermission.java
index 7b6c656..51b00fa 100644
--- a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewarePermission.java
+++ b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewarePermission.java
@@ -236,7 +236,8 @@
@Override
public void unloadModel(int modelHandle) throws RemoteException {
- enforcePermissions();
+ // Unloading a model does not require special permissions. Having a handle to the
+ // session is sufficient.
mDelegate.unloadModel(modelHandle);
}
@@ -250,7 +251,8 @@
@Override
public void stopRecognition(int modelHandle) throws RemoteException {
- enforcePermissions();
+ // Stopping a model does not require special permissions. Having a handle to the
+ // session is sufficient.
mDelegate.stopRecognition(modelHandle);
}
@@ -284,7 +286,8 @@
@Override
public void detach() throws RemoteException {
- enforcePermissions();
+ // Detaching does not require special permissions. Having a handle to the session is
+ // sufficient.
mDelegate.detach();
}
diff --git a/services/core/java/com/android/server/timezonedetector/ConfigurationInternal.java b/services/core/java/com/android/server/timezonedetector/ConfigurationInternal.java
index 9e76bc1..08eaa29 100644
--- a/services/core/java/com/android/server/timezonedetector/ConfigurationInternal.java
+++ b/services/core/java/com/android/server/timezonedetector/ConfigurationInternal.java
@@ -138,7 +138,7 @@
configureGeolocationDetectionEnabledCapability = CAPABILITY_NOT_SUPPORTED;
} else if (!allowConfigDateTime) {
configureGeolocationDetectionEnabledCapability = CAPABILITY_NOT_ALLOWED;
- } else if (!isLocationEnabled()) {
+ } else if (!mAutoDetectionEnabled || !isLocationEnabled()) {
configureGeolocationDetectionEnabledCapability = CAPABILITY_NOT_APPLICABLE;
} else {
configureGeolocationDetectionEnabledCapability = CAPABILITY_POSSESSED;
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java
index d09cd38..68a086d 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java
@@ -30,6 +30,7 @@
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ShellCallback;
+import android.os.SystemProperties;
import android.util.ArrayMap;
import android.util.IndentingPrintWriter;
import android.util.Slog;
@@ -58,11 +59,14 @@
private static final String TAG = "TimeZoneDetectorService";
/**
- * A compile time constant "feature switch" for enabling / disabling location-based time zone
- * detection on Android. If this is {@code false}, there should be few / little changes in
- * behavior with previous releases and little overhead associated with geolocation components.
+ * A "feature switch" for enabling / disabling location-based time zone detection. If this is
+ * {@code false}, there should be few / little changes in behavior with previous releases and
+ * little overhead associated with geolocation components.
+ * TODO(b/151304765) Remove this when the feature is on for all.
*/
- public static final boolean GEOLOCATION_TIME_ZONE_DETECTION_ENABLED = false;
+ public static final boolean GEOLOCATION_TIME_ZONE_DETECTION_ENABLED =
+ SystemProperties.getBoolean(
+ "persist.sys.location_time_zone_detection_feature_enabled", false);
/**
* Handles the service lifecycle for {@link TimeZoneDetectorService} and
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index 7b044ed..149dbd0 100755
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -54,7 +54,7 @@
import android.media.tv.ITvInputServiceCallback;
import android.media.tv.ITvInputSession;
import android.media.tv.ITvInputSessionCallback;
-import android.media.tv.TvChannelInfo;
+import android.media.tv.TunedInfo;
import android.media.tv.TvContentRating;
import android.media.tv.TvContentRatingSystemInfo;
import android.media.tv.TvContract;
@@ -90,7 +90,6 @@
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.IoThread;
import com.android.server.SystemService;
-import com.android.server.SystemService.TargetUser;
import java.io.File;
import java.io.FileDescriptor;
@@ -114,7 +113,7 @@
private static final boolean DEBUG = false;
private static final String TAG = "TvInputManagerService";
private static final String DVB_DIRECTORY = "/dev/dvb";
- private static final int APP_TAG_SELF = TvChannelInfo.APP_TAG_SELF;
+ private static final int APP_TAG_SELF = TunedInfo.APP_TAG_SELF;
private static final String PERMISSION_ACCESS_WATCHED_PROGRAMS =
"com.android.providers.tv.permission.ACCESS_WATCHED_PROGRAMS";
@@ -860,9 +859,9 @@
try {
ITvInputManagerCallback callback = userState.mCallbacks.getBroadcastItem(i);
Pair<Integer, Integer> pidUid = userState.callbackPidUidMap.get(callback);
- List<TvChannelInfo> infos = getCurrentTvChannelInfosInternalLocked(
+ List<TunedInfo> infos = getCurrentTunedInfosInternalLocked(
userState, pidUid.first, pidUid.second);
- callback.onCurrentTvChannelInfosUpdated(infos);
+ callback.onCurrentTunedInfosUpdated(infos);
} catch (RemoteException e) {
Slog.e(TAG, "failed to report updated current channel infos to callback", e);
}
@@ -2097,14 +2096,14 @@
}
@Override
- public List<TvChannelInfo> getCurrentTvChannelInfos(@UserIdInt int userId) {
+ public List<TunedInfo> getCurrentTunedInfos(@UserIdInt int userId) {
int callingPid = Binder.getCallingPid();
int callingUid = Binder.getCallingUid();
final int resolvedUserId = resolveCallingUserId(callingPid, callingUid, userId,
"getTvCurrentChannelInfos");
synchronized (mLock) {
UserState userState = getOrCreateUserStateLocked(resolvedUserId);
- return getCurrentTvChannelInfosInternalLocked(userState, callingPid, callingUid);
+ return getCurrentTunedInfosInternalLocked(userState, callingPid, callingUid);
}
}
@@ -2278,9 +2277,9 @@
}
}
- private List<TvChannelInfo> getCurrentTvChannelInfosInternalLocked(
+ private List<TunedInfo> getCurrentTunedInfosInternalLocked(
UserState userState, int callingPid, int callingUid) {
- List<TvChannelInfo> channelInfos = new ArrayList<>();
+ List<TunedInfo> channelInfos = new ArrayList<>();
boolean watchedProgramsAccess = hasAccessWatchedProgramsPermission(callingPid, callingUid);
for (SessionState state : userState.sessionStateMap.values()) {
if (state.isCurrent) {
@@ -2288,7 +2287,7 @@
int appType;
if (state.callingUid == callingUid) {
appTag = APP_TAG_SELF;
- appType = TvChannelInfo.APP_TYPE_SELF;
+ appType = TunedInfo.APP_TYPE_SELF;
} else {
appTag = userState.mAppTagMap.get(state.callingUid);
if (appTag == null) {
@@ -2296,10 +2295,10 @@
userState.mAppTagMap.put(state.callingUid, appTag);
}
appType = isSystemApp(state.componentName.getPackageName())
- ? TvChannelInfo.APP_TYPE_SYSTEM
- : TvChannelInfo.APP_TYPE_NON_SYSTEM;
+ ? TunedInfo.APP_TYPE_SYSTEM
+ : TunedInfo.APP_TYPE_NON_SYSTEM;
}
- channelInfos.add(new TvChannelInfo(
+ channelInfos.add(new TunedInfo(
state.inputId,
watchedProgramsAccess ? state.currentChannel : null,
state.isRecordingSession,
diff --git a/services/core/java/com/android/server/vcn/OWNERS b/services/core/java/com/android/server/vcn/OWNERS
new file mode 100644
index 0000000..33b9f0f
--- /dev/null
+++ b/services/core/java/com/android/server/vcn/OWNERS
@@ -0,0 +1,7 @@
+set noparent
+
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
\ No newline at end of file
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 28e71fa..c8a8f81 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -1358,6 +1358,12 @@
}
return false;
}
+ // don't abort if the callingUid has SYSTEM_ALERT_WINDOW permission
+ if (mService.hasSystemAlertWindowPermission(callingUid, callingPid, callingPackage)) {
+ Slog.w(TAG, "Background activity start for " + callingPackage
+ + " allowed because SYSTEM_ALERT_WINDOW permission is granted.");
+ return false;
+ }
// If we don't have callerApp at this point, no caller was provided to startActivity().
// That's the case for PendingIntent-based starts, since the creator's process might not be
// up and alive. If that's the case, we retrieve the WindowProcessController for the send()
@@ -1394,12 +1400,6 @@
}
}
}
- // don't abort if the callingUid has SYSTEM_ALERT_WINDOW permission
- if (mService.hasSystemAlertWindowPermission(callingUid, callingPid, callingPackage)) {
- Slog.w(TAG, "Background activity start for " + callingPackage
- + " allowed because SYSTEM_ALERT_WINDOW permission is granted.");
- return false;
- }
// anything that has fallen through would currently be aborted
Slog.w(TAG, "Background activity start [callingPackage: " + callingPackage
+ "; callingUid: " + callingUid
diff --git a/services/core/java/com/android/server/wm/BackgroundActivityStartCallback.java b/services/core/java/com/android/server/wm/BackgroundActivityStartCallback.java
index 4e742b9..af6c255 100644
--- a/services/core/java/com/android/server/wm/BackgroundActivityStartCallback.java
+++ b/services/core/java/com/android/server/wm/BackgroundActivityStartCallback.java
@@ -24,8 +24,8 @@
*/
public interface BackgroundActivityStartCallback {
/**
- * The token that allowed the activity start that triggered {@link
- * #onExclusiveTokenActivityStart()}.
+ * The token for which this callback is responsible for deciding whether the app can start
+ * background activities or not.
*
* Ideally this should just return a final variable, don't do anything costly here (don't hold
* any locks).
@@ -33,7 +33,10 @@
IBinder getToken();
/**
- * Called when the background activity start happens.
+ * Returns true if the background activity start due to originating token in {@link #getToken()}
+ * should be allowed or not.
+ *
+ * This will be called holding the WM lock, don't do anything costly here.
*/
- void onExclusiveTokenActivityStart(String packageName);
+ boolean isActivityStartAllowed(int uid, String packageName);
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index dafa07e..e7f0e3e 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -253,10 +253,23 @@
ActivityTaskManagerService mAtmService;
- /** Unique identifier of this display. */
+ /**
+ * Unique logical identifier of this display.
+ *
+ * @see DisplayInfo#displayId
+ */
final int mDisplayId;
/**
+ * Unique physical identifier of this display. Unlike {@link #mDisplayId} this value can change
+ * at runtime if the underlying physical display changes.
+ *
+ * @see DisplayInfo#uniqueId
+ */
+ @Nullable
+ String mCurrentUniqueDisplayId;
+
+ /**
* We organize all top-level Surfaces into the following layer.
* It contains a few Surfaces which are always on top of others, and omitted from
* Screen-Magnification, for example the strict mode flash or the fullscreen magnification
@@ -916,6 +929,7 @@
mAtmService = mWmService.mAtmService;
mDisplay = display;
mDisplayId = display.getDisplayId();
+ mCurrentUniqueDisplayId = display.getUniqueId();
mOffTokenAcquirer = mRootWindowContainer.mDisplayOffTokenAcquirer;
mWallpaperController = new WallpaperController(mWmService, this);
display.getDisplayInfo(mDisplayInfo);
@@ -2417,13 +2431,20 @@
final int newHeight = rotated ? mDisplayInfo.logicalWidth : mDisplayInfo.logicalHeight;
final int newDensity = mDisplayInfo.logicalDensityDpi;
final DisplayCutout newCutout = mDisplayInfo.displayCutout;
+ final String newUniqueId = mDisplayInfo.uniqueId;
final boolean displayMetricsChanged = mInitialDisplayWidth != newWidth
|| mInitialDisplayHeight != newHeight
|| mInitialDisplayDensity != mDisplayInfo.logicalDensityDpi
|| !Objects.equals(mInitialDisplayCutout, newCutout);
+ final boolean physicalDisplayChanged = !newUniqueId.equals(mCurrentUniqueDisplayId);
- if (displayMetricsChanged) {
+ if (displayMetricsChanged || physicalDisplayChanged) {
+ if (physicalDisplayChanged) {
+ // Reapply the window settings as the underlying physical display has changed.
+ mWmService.mDisplayWindowSettings.applySettingsToDisplayLocked(this);
+ }
+
// If there is an override set for base values - use it, otherwise use new values.
updateBaseDisplayMetrics(mIsSizeForced ? mBaseDisplayWidth : newWidth,
mIsSizeForced ? mBaseDisplayHeight : newHeight,
@@ -2434,6 +2455,7 @@
mInitialDisplayHeight = newHeight;
mInitialDisplayDensity = newDensity;
mInitialDisplayCutout = newCutout;
+ mCurrentUniqueDisplayId = newUniqueId;
reconfigureDisplayLocked();
}
}
@@ -2452,6 +2474,10 @@
/** Update base (override) display metrics. */
void updateBaseDisplayMetrics(int baseWidth, int baseHeight, int baseDensity) {
+ final int originalWidth = mBaseDisplayWidth;
+ final int originalHeight = mBaseDisplayHeight;
+ final int originalDensity = mBaseDisplayDensity;
+
mBaseDisplayWidth = baseWidth;
mBaseDisplayHeight = baseHeight;
mBaseDisplayDensity = baseDensity;
@@ -2466,9 +2492,11 @@
}
}
- mBaseDisplayRect.set(0, 0, mBaseDisplayWidth, mBaseDisplayHeight);
-
- updateBounds();
+ if (mBaseDisplayWidth != originalWidth || mBaseDisplayHeight != originalHeight
+ || mBaseDisplayDensity != originalDensity) {
+ mBaseDisplayRect.set(0, 0, mBaseDisplayWidth, mBaseDisplayHeight);
+ updateBounds();
+ }
}
/**
diff --git a/services/core/java/com/android/server/wm/DisplayWindowSettings.java b/services/core/java/com/android/server/wm/DisplayWindowSettings.java
index c8c83a6..04e37fa 100644
--- a/services/core/java/com/android/server/wm/DisplayWindowSettings.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowSettings.java
@@ -385,13 +385,16 @@
dc.getDisplayRotation().restoreSettings(entry.mUserRotationMode,
entry.mUserRotation, entry.mFixedToUserRotation);
- if (entry.mForcedDensity != 0) {
- dc.mBaseDisplayDensity = entry.mForcedDensity;
- }
- if (entry.mForcedWidth != 0 && entry.mForcedHeight != 0) {
- dc.updateBaseDisplayMetrics(entry.mForcedWidth, entry.mForcedHeight,
- dc.mBaseDisplayDensity);
- }
+ final boolean hasDensityOverride = entry.mForcedDensity != 0;
+ final boolean hasSizeOverride = entry.mForcedWidth != 0 && entry.mForcedHeight != 0;
+ dc.mIsDensityForced = hasDensityOverride;
+ dc.mIsSizeForced = hasSizeOverride;
+
+ final int width = hasSizeOverride ? entry.mForcedWidth : dc.mBaseDisplayWidth;
+ final int height = hasSizeOverride ? entry.mForcedHeight : dc.mBaseDisplayHeight;
+ final int density = hasDensityOverride ? entry.mForcedDensity : dc.mBaseDisplayDensity;
+ dc.updateBaseDisplayMetrics(width, height, density);
+
dc.mDisplayScalingDisabled = entry.mForcedScalingMode == FORCE_SCALING_MODE_DISABLED;
}
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 803a533..143b657 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -265,6 +265,7 @@
consumer.mWindowHandle.layoutParamsFlags |= FLAG_NOT_TOUCH_MODAL;
break;
case INPUT_CONSUMER_RECENTS_ANIMATION:
+ consumer.mWindowHandle.focusable = true;
break;
default:
throw new IllegalArgumentException("Illegal input consumer : " + name
@@ -545,7 +546,7 @@
if (mAddRecentsAnimationInputConsumerHandle && shouldApplyRecentsInputConsumer) {
if (recentsAnimationController.updateInputConsumerForApp(
- mRecentsAnimationInputConsumer.mWindowHandle, focusable)) {
+ mRecentsAnimationInputConsumer.mWindowHandle)) {
mRecentsAnimationInputConsumer.show(mInputTransaction, w);
mAddRecentsAnimationInputConsumerHandle = false;
}
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index a40b310..dda1e2d 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -827,15 +827,13 @@
&& !isTargetApp(activity) && isAnimatingApp(activity);
}
- boolean updateInputConsumerForApp(InputWindowHandle inputWindowHandle,
- boolean focusable) {
+ boolean updateInputConsumerForApp(InputWindowHandle inputWindowHandle) {
// Update the input consumer touchable region to match the target app main window
final WindowState targetAppMainWindow = mTargetActivityRecord != null
? mTargetActivityRecord.findMainWindow()
: null;
if (targetAppMainWindow != null) {
targetAppMainWindow.getBounds(mTmpRect);
- inputWindowHandle.focusable = focusable;
inputWindowHandle.touchableRegion.set(mTmpRect);
return true;
}
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index fb9bdf5..e8a7a9c 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -223,7 +223,7 @@
private boolean mRunningRemoteAnimation;
@Nullable
- private BackgroundActivityStartCallback mBackgroundActivityStartCallback;
+ private final BackgroundActivityStartCallback mBackgroundActivityStartCallback;
/** The state for oom-adjustment calculation. */
private final OomScoreReferenceState mOomRefState;
@@ -555,8 +555,7 @@
return true;
}
// allow if the flag was explicitly set
- if (!mBackgroundActivityStartTokens.isEmpty()) {
- onBackgroundStartAllowedByToken();
+ if (isBackgroundStartAllowedByToken()) {
if (DEBUG_ACTIVITY_STARTS) {
Slog.d(TAG, "[WindowProcessController(" + mPid
+ ")] Activity start allowed: process allowed by token");
@@ -566,18 +565,29 @@
return false;
}
- private void onBackgroundStartAllowedByToken() {
+ /**
+ * If there are no tokens, we don't allow *by token*. If there are tokens, we need to check if
+ * the callback handles all the tokens, if so we ask the callback if the activity should be
+ * started, otherwise we allow.
+ */
+ private boolean isBackgroundStartAllowedByToken() {
+ if (mBackgroundActivityStartTokens.isEmpty()) {
+ return false;
+ }
if (mBackgroundActivityStartCallback == null) {
- return;
+ // We have tokens but no callback to decide => allow
+ return true;
}
IBinder callbackToken = mBackgroundActivityStartCallback.getToken();
for (IBinder token : mBackgroundActivityStartTokens.values()) {
if (token != callbackToken) {
- return;
+ // The callback doesn't handle all the tokens => allow
+ return true;
}
}
- mAtm.mH.post(() ->
- mBackgroundActivityStartCallback.onExclusiveTokenActivityStart(mInfo.packageName));
+ // The callback handles all the tokens => callback decides
+ return mBackgroundActivityStartCallback.isActivityStartAllowed(mInfo.uid,
+ mInfo.packageName);
}
private boolean isBoundByForegroundUid() {
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index 160ad89..cbe0a42 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -30,7 +30,6 @@
import static com.android.server.wm.WindowSurfaceControllerProto.LAYER;
import static com.android.server.wm.WindowSurfaceControllerProto.SHOWN;
-import android.graphics.Rect;
import android.graphics.Region;
import android.os.Debug;
import android.os.Trace;
@@ -62,7 +61,6 @@
private float mSurfaceY = 0;
private int mSurfaceW = 0;
private int mSurfaceH = 0;
- private Rect mSurfaceCrop = new Rect(0, 0, -1, -1);
// Initialize to the identity matrix.
private float mLastDsdx = 1;
@@ -74,13 +72,6 @@
private int mSurfaceLayer = 0;
- // Surface flinger doesn't support crop rectangles where width or height is non-positive.
- // However, we need to somehow handle the situation where the cropping would completely hide
- // the window. We achieve this by explicitly hiding the surface and not letting it be shown.
- private boolean mHiddenForCrop = false;
-
- // Initially a surface is hidden after just being created.
- private boolean mHiddenForOtherReasons = true;
private final String title;
private final WindowManagerService mService;
@@ -140,13 +131,6 @@
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
- void reparentChildrenInTransaction(WindowSurfaceController other) {
- ProtoLog.i(WM_SHOW_TRANSACTIONS, "REPARENT from: %s to: %s", this, other);
- if ((mSurfaceControl != null) && (other.mSurfaceControl != null)) {
- mSurfaceControl.reparentChildren(other.mSurfaceControl);
- }
- }
-
void detachChildren() {
ProtoLog.i(WM_SHOW_TRANSACTIONS, "SEVER CHILDREN");
mChildrenDetached = true;
@@ -157,7 +141,6 @@
void hide(SurfaceControl.Transaction transaction, String reason) {
ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE HIDE ( %s ): %s", reason, title);
- mHiddenForOtherReasons = true;
mAnimator.destroyPreservedSurfaceLocked();
if (mSurfaceShown) {
@@ -195,47 +178,6 @@
}
}
- void setCropInTransaction(Rect clipRect, boolean recoveringMemory) {
- ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE CROP %s: %s", clipRect.toShortString(), title);
- try {
- if (clipRect.width() > 0 && clipRect.height() > 0) {
- if (!clipRect.equals(mSurfaceCrop)) {
- mSurfaceControl.setWindowCrop(clipRect);
- mSurfaceCrop.set(clipRect);
- }
- mHiddenForCrop = false;
- updateVisibility();
- } else {
- mHiddenForCrop = true;
- mAnimator.destroyPreservedSurfaceLocked();
- updateVisibility();
- }
- } catch (RuntimeException e) {
- Slog.w(TAG, "Error setting crop surface of " + this
- + " crop=" + clipRect.toShortString(), e);
- if (!recoveringMemory) {
- mAnimator.reclaimSomeSurfaceMemory("crop", true);
- }
- }
- }
-
- void clearCropInTransaction(boolean recoveringMemory) {
- ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE CLEAR CROP: %s", title);
- try {
- Rect clipRect = new Rect(0, 0, -1, -1);
- if (mSurfaceCrop.equals(clipRect)) {
- return;
- }
- mSurfaceControl.setWindowCrop(clipRect);
- mSurfaceCrop.set(clipRect);
- } catch (RuntimeException e) {
- Slog.w(TAG, "Error setting clearing crop of " + this, e);
- if (!recoveringMemory) {
- mAnimator.reclaimSomeSurfaceMemory("crop", true);
- }
- }
- }
-
void setPosition(SurfaceControl.Transaction t, float left, float top,
boolean recoveringMemory) {
final boolean surfaceMoved = mSurfaceX != left || mSurfaceY != top;
@@ -287,31 +229,6 @@
}
}
- boolean setBufferSizeInTransaction(int width, int height, boolean recoveringMemory) {
- final boolean surfaceResized = mSurfaceW != width || mSurfaceH != height;
- if (surfaceResized) {
- mSurfaceW = width;
- mSurfaceH = height;
-
- try {
- ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE SIZE %dx%d: %s", width, height, title);
- mSurfaceControl.setBufferSize(width, height);
- } catch (RuntimeException e) {
- // If something goes wrong with the surface (such
- // as running out of memory), don't take down the
- // entire system.
- Slog.e(TAG, "Error resizing surface of " + title
- + " size=(" + width + "x" + height + ")", e);
- if (!recoveringMemory) {
- mAnimator.reclaimSomeSurfaceMemory("size", true);
- }
- return false;
- }
- return true;
- }
- return false;
- }
-
boolean prepareToShowInTransaction(float alpha,
float dsdx, float dtdx, float dsdy,
float dtdy, boolean recoveringMemory) {
@@ -404,35 +321,15 @@
}
}
- void getContainerRect(Rect rect) {
- mAnimator.getContainerRect(rect);
- }
-
boolean showRobustlyInTransaction() {
ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE SHOW (performLayout): %s", title);
if (DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + this
+ " during relayout");
- mHiddenForOtherReasons = false;
- return updateVisibility();
- }
- private boolean updateVisibility() {
- if (mHiddenForCrop || mHiddenForOtherReasons) {
- if (mSurfaceShown) {
- hideSurface(mTmpTransaction);
- SurfaceControl.mergeToGlobalTransaction(mTmpTransaction);
- }
- return false;
- } else {
- if (!mSurfaceShown) {
- return showSurface();
- } else {
- return true;
- }
+ if (mSurfaceShown) {
+ return true;
}
- }
- private boolean showSurface() {
try {
setShown(true);
mSurfaceControl.show();
@@ -442,15 +339,9 @@
}
mAnimator.reclaimSomeSurfaceMemory("show", true);
-
return false;
}
- void deferTransactionUntil(SurfaceControl barrier, long frame) {
- // TODO: Logging
- mSurfaceControl.deferTransactionUntil(barrier, frame);
- }
-
void forceScaleableInTransaction(boolean force) {
// -1 means we don't override the default or client specified
// scaling mode.
@@ -472,7 +363,6 @@
return mSurfaceControl.getContentFrameStats(outStats);
}
-
boolean hasSurface() {
return mSurfaceControl != null;
}
@@ -487,10 +377,6 @@
}
}
- int getLayer() {
- return mSurfaceLayer;
- }
-
boolean getShown() {
return mSurfaceShown;
}
@@ -507,14 +393,6 @@
}
}
- float getX() {
- return mSurfaceX;
- }
-
- float getY() {
- return mSurfaceY;
- }
-
int getWidth() {
return mSurfaceW;
}
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 4413dc3..c1d5f19 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -99,6 +99,7 @@
jmethodID notifyInputChannelBroken;
jmethodID notifyANR;
jmethodID notifyFocusChanged;
+ jmethodID notifyUntrustedTouch;
jmethodID filterInputEvent;
jmethodID interceptKeyBeforeQueueing;
jmethodID interceptMotionBeforeQueueingNonInteractive;
@@ -256,6 +257,7 @@
const sp<IBinder>& token, const std::string& reason) override;
void notifyInputChannelBroken(const sp<IBinder>& token) override;
void notifyFocusChanged(const sp<IBinder>& oldToken, const sp<IBinder>& newToken) override;
+ void notifyUntrustedTouch(const std::string& obscuringPackage) override;
bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) override;
void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) override;
void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags) override;
@@ -755,6 +757,17 @@
}
}
+void NativeInputManager::notifyUntrustedTouch(const std::string& obscuringPackage) {
+#if DEBUG_INPUT_DISPATCHER_POLICY
+ ALOGD("notifyUntrustedTouch - obscuringPackage=%s", obscuringPackage.c_str());
+#endif
+ ATRACE_CALL();
+ JNIEnv* env = jniEnv();
+ jstring jPackage = env->NewStringUTF(obscuringPackage.c_str());
+ env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifyUntrustedTouch, jPackage);
+ checkAndClearExceptionFromCallback(env, "notifyUntrustedTouch");
+}
+
void NativeInputManager::notifyFocusChanged(const sp<IBinder>& oldToken,
const sp<IBinder>& newToken) {
#if DEBUG_INPUT_DISPATCHER_POLICY
@@ -1893,6 +1906,9 @@
GET_METHOD_ID(gServiceClassInfo.notifyFocusChanged, clazz,
"notifyFocusChanged", "(Landroid/os/IBinder;Landroid/os/IBinder;)V");
+ GET_METHOD_ID(gServiceClassInfo.notifyUntrustedTouch, clazz, "notifyUntrustedTouch",
+ "(Ljava/lang/String;)V");
+
GET_METHOD_ID(gServiceClassInfo.notifyANR, clazz,
"notifyANR",
"(Landroid/view/InputApplicationHandle;Landroid/os/IBinder;Ljava/lang/String;)J");
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index b7d94c1..36ff974 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -411,37 +411,37 @@
private static final int STATUS_BAR_DISABLE2_MASK =
StatusBarManager.DISABLE2_QUICK_SETTINGS;
- private static final Set<String> SECURE_SETTINGS_WHITELIST;
- private static final Set<String> SECURE_SETTINGS_DEVICEOWNER_WHITELIST;
- private static final Set<String> GLOBAL_SETTINGS_WHITELIST;
+ private static final Set<String> SECURE_SETTINGS_ALLOWLIST;
+ private static final Set<String> SECURE_SETTINGS_DEVICEOWNER_ALLOWLIST;
+ private static final Set<String> GLOBAL_SETTINGS_ALLOWLIST;
private static final Set<String> GLOBAL_SETTINGS_DEPRECATED;
- private static final Set<String> SYSTEM_SETTINGS_WHITELIST;
+ private static final Set<String> SYSTEM_SETTINGS_ALLOWLIST;
private static final Set<Integer> DA_DISALLOWED_POLICIES;
// A collection of user restrictions that are deprecated and should simply be ignored.
private static final String AB_DEVICE_KEY = "ro.build.ab_update";
static {
- SECURE_SETTINGS_WHITELIST = new ArraySet<>();
- SECURE_SETTINGS_WHITELIST.add(Settings.Secure.DEFAULT_INPUT_METHOD);
- SECURE_SETTINGS_WHITELIST.add(Settings.Secure.SKIP_FIRST_USE_HINTS);
- SECURE_SETTINGS_WHITELIST.add(Settings.Secure.INSTALL_NON_MARKET_APPS);
+ SECURE_SETTINGS_ALLOWLIST = new ArraySet<>();
+ SECURE_SETTINGS_ALLOWLIST.add(Settings.Secure.DEFAULT_INPUT_METHOD);
+ SECURE_SETTINGS_ALLOWLIST.add(Settings.Secure.SKIP_FIRST_USE_HINTS);
+ SECURE_SETTINGS_ALLOWLIST.add(Settings.Secure.INSTALL_NON_MARKET_APPS);
- SECURE_SETTINGS_DEVICEOWNER_WHITELIST = new ArraySet<>();
- SECURE_SETTINGS_DEVICEOWNER_WHITELIST.addAll(SECURE_SETTINGS_WHITELIST);
- SECURE_SETTINGS_DEVICEOWNER_WHITELIST.add(Settings.Secure.LOCATION_MODE);
+ SECURE_SETTINGS_DEVICEOWNER_ALLOWLIST = new ArraySet<>();
+ SECURE_SETTINGS_DEVICEOWNER_ALLOWLIST.addAll(SECURE_SETTINGS_ALLOWLIST);
+ SECURE_SETTINGS_DEVICEOWNER_ALLOWLIST.add(Settings.Secure.LOCATION_MODE);
- GLOBAL_SETTINGS_WHITELIST = new ArraySet<>();
- GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.ADB_ENABLED);
- GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.ADB_WIFI_ENABLED);
- GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.AUTO_TIME);
- GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.AUTO_TIME_ZONE);
- GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.DATA_ROAMING);
- GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.USB_MASS_STORAGE_ENABLED);
- GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.WIFI_SLEEP_POLICY);
- GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.STAY_ON_WHILE_PLUGGED_IN);
- GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN);
- GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.PRIVATE_DNS_MODE);
- GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.PRIVATE_DNS_SPECIFIER);
+ GLOBAL_SETTINGS_ALLOWLIST = new ArraySet<>();
+ GLOBAL_SETTINGS_ALLOWLIST.add(Settings.Global.ADB_ENABLED);
+ GLOBAL_SETTINGS_ALLOWLIST.add(Settings.Global.ADB_WIFI_ENABLED);
+ GLOBAL_SETTINGS_ALLOWLIST.add(Settings.Global.AUTO_TIME);
+ GLOBAL_SETTINGS_ALLOWLIST.add(Settings.Global.AUTO_TIME_ZONE);
+ GLOBAL_SETTINGS_ALLOWLIST.add(Settings.Global.DATA_ROAMING);
+ GLOBAL_SETTINGS_ALLOWLIST.add(Settings.Global.USB_MASS_STORAGE_ENABLED);
+ GLOBAL_SETTINGS_ALLOWLIST.add(Settings.Global.WIFI_SLEEP_POLICY);
+ GLOBAL_SETTINGS_ALLOWLIST.add(Settings.Global.STAY_ON_WHILE_PLUGGED_IN);
+ GLOBAL_SETTINGS_ALLOWLIST.add(Settings.Global.WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN);
+ GLOBAL_SETTINGS_ALLOWLIST.add(Settings.Global.PRIVATE_DNS_MODE);
+ GLOBAL_SETTINGS_ALLOWLIST.add(Settings.Global.PRIVATE_DNS_SPECIFIER);
GLOBAL_SETTINGS_DEPRECATED = new ArraySet<>();
GLOBAL_SETTINGS_DEPRECATED.add(Settings.Global.BLUETOOTH_ON);
@@ -450,11 +450,11 @@
GLOBAL_SETTINGS_DEPRECATED.add(Settings.Global.NETWORK_PREFERENCE);
GLOBAL_SETTINGS_DEPRECATED.add(Settings.Global.WIFI_ON);
- SYSTEM_SETTINGS_WHITELIST = new ArraySet<>();
- SYSTEM_SETTINGS_WHITELIST.add(Settings.System.SCREEN_BRIGHTNESS);
- SYSTEM_SETTINGS_WHITELIST.add(Settings.System.SCREEN_BRIGHTNESS_FLOAT);
- SYSTEM_SETTINGS_WHITELIST.add(Settings.System.SCREEN_BRIGHTNESS_MODE);
- SYSTEM_SETTINGS_WHITELIST.add(Settings.System.SCREEN_OFF_TIMEOUT);
+ SYSTEM_SETTINGS_ALLOWLIST = new ArraySet<>();
+ SYSTEM_SETTINGS_ALLOWLIST.add(Settings.System.SCREEN_BRIGHTNESS);
+ SYSTEM_SETTINGS_ALLOWLIST.add(Settings.System.SCREEN_BRIGHTNESS_FLOAT);
+ SYSTEM_SETTINGS_ALLOWLIST.add(Settings.System.SCREEN_BRIGHTNESS_MODE);
+ SYSTEM_SETTINGS_ALLOWLIST.add(Settings.System.SCREEN_OFF_TIMEOUT);
DA_DISALLOWED_POLICIES = new ArraySet<>();
DA_DISALLOWED_POLICIES.add(DeviceAdminInfo.USES_POLICY_DISABLE_CAMERA);
@@ -1733,7 +1733,7 @@
final IIntentSender.Stub mLocalSender = new IIntentSender.Stub() {
@Override
- public void send(int code, Intent intent, String resolvedType, IBinder whitelistToken,
+ public void send(int code, Intent intent, String resolvedType, IBinder allowlistToken,
IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
final int status = intent.getIntExtra(
PackageInstaller.EXTRA_STATUS, PackageInstaller.STATUS_FAILURE);
@@ -5660,7 +5660,7 @@
*/
@Override
public boolean setAlwaysOnVpnPackage(ComponentName who, String vpnPackage, boolean lockdown,
- List<String> lockdownWhitelist)
+ List<String> lockdownAllowlist)
throws SecurityException {
Objects.requireNonNull(who, "ComponentName is null");
@@ -5675,10 +5675,10 @@
DevicePolicyManager.ERROR_VPN_PACKAGE_NOT_FOUND, vpnPackage);
}
- if (vpnPackage != null && lockdown && lockdownWhitelist != null) {
- for (String packageName : lockdownWhitelist) {
+ if (vpnPackage != null && lockdown && lockdownAllowlist != null) {
+ for (String packageName : lockdownAllowlist) {
if (!isPackageInstalledForUser(packageName, userId)) {
- Slog.w(LOG_TAG, "Non-existent package in VPN whitelist: " + packageName);
+ Slog.w(LOG_TAG, "Non-existent package in VPN allowlist: " + packageName);
throw new ServiceSpecificException(
DevicePolicyManager.ERROR_VPN_PACKAGE_NOT_FOUND, packageName);
}
@@ -5686,7 +5686,7 @@
}
// If some package is uninstalled after the check above, it will be ignored by CM.
if (!mInjector.getConnectivityManager().setAlwaysOnVpnPackageForUser(
- userId, vpnPackage, lockdown, lockdownWhitelist)) {
+ userId, vpnPackage, lockdown, lockdownAllowlist)) {
throw new UnsupportedOperationException();
}
DevicePolicyEventLogger
@@ -5694,7 +5694,7 @@
.setAdmin(caller.getComponentName())
.setStrings(vpnPackage)
.setBoolean(lockdown)
- .setInt(lockdownWhitelist != null ? lockdownWhitelist.size() : 0)
+ .setInt(lockdownAllowlist != null ? lockdownAllowlist.size() : 0)
.write();
});
synchronized (getLockObject()) {
@@ -5752,7 +5752,7 @@
}
@Override
- public List<String> getAlwaysOnVpnLockdownWhitelist(ComponentName admin)
+ public List<String> getAlwaysOnVpnLockdownAllowlist(ComponentName admin)
throws SecurityException {
Objects.requireNonNull(admin, "ComponentName is null");
@@ -10475,7 +10475,7 @@
return;
}
- if (!GLOBAL_SETTINGS_WHITELIST.contains(setting)
+ if (!GLOBAL_SETTINGS_ALLOWLIST.contains(setting)
&& !UserManager.isDeviceInDemoMode(mContext)) {
throw new SecurityException(String.format(
"Permission denial: device owners cannot update %1$s", setting));
@@ -10503,7 +10503,7 @@
synchronized (getLockObject()) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
- if (!SYSTEM_SETTINGS_WHITELIST.contains(setting)) {
+ if (!SYSTEM_SETTINGS_ALLOWLIST.contains(setting)) {
throw new SecurityException(String.format(
"Permission denial: device owners cannot update %1$s", setting));
}
@@ -10663,12 +10663,12 @@
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
if (isDeviceOwner(who, callingUserId)) {
- if (!SECURE_SETTINGS_DEVICEOWNER_WHITELIST.contains(setting)
+ if (!SECURE_SETTINGS_DEVICEOWNER_ALLOWLIST.contains(setting)
&& !isCurrentUserDemo()) {
throw new SecurityException(String.format(
"Permission denial: Device owners cannot update %1$s", setting));
}
- } else if (!SECURE_SETTINGS_WHITELIST.contains(setting) && !isCurrentUserDemo()) {
+ } else if (!SECURE_SETTINGS_ALLOWLIST.contains(setting) && !isCurrentUserDemo()) {
throw new SecurityException(String.format(
"Permission denial: Profile owners cannot update %1$s", setting));
}
@@ -12484,7 +12484,7 @@
@Override
public void markProfileOwnerOnOrganizationOwnedDevice(ComponentName who, int userId) {
// As the caller is the system, it must specify the component name of the profile owner
- // as a sanity / safety check.
+ // as a safety check.
Objects.requireNonNull(who);
if (!mHasFeature) {
@@ -12520,7 +12520,7 @@
@GuardedBy("getLockObject()")
private void markProfileOwnerOnOrganizationOwnedDeviceUncheckedLocked(
ComponentName who, int userId) {
- // Sanity check: Make sure that the user has a profile owner and that the specified
+ // Make sure that the user has a profile owner and that the specified
// component is the profile owner of that user.
if (!isProfileOwner(who, userId)) {
throw new IllegalArgumentException(String.format(
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 177cb1a..275d8f1 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -280,6 +280,8 @@
"com.android.server.autofill.AutofillManagerService";
private static final String CONTENT_CAPTURE_MANAGER_SERVICE_CLASS =
"com.android.server.contentcapture.ContentCaptureManagerService";
+ private static final String MUSIC_RECOGNITION_MANAGER_SERVICE_CLASS =
+ "com.android.server.musicrecognition.MusicRecognitionManagerService";
private static final String SYSTEM_CAPTIONS_MANAGER_SERVICE_CLASS =
"com.android.server.systemcaptions.SystemCaptionsManagerService";
private static final String TIME_ZONE_RULES_MANAGER_SERVICE_CLASS =
@@ -1415,6 +1417,17 @@
t.traceEnd();
}
+ if (deviceHasConfigString(context,
+ R.string.config_defaultMusicRecognitionService)) {
+ t.traceBegin("StartMusicRecognitionManagerService");
+ mSystemServiceManager.startService(MUSIC_RECOGNITION_MANAGER_SERVICE_CLASS);
+ t.traceEnd();
+ } else {
+ Slog.d(TAG,
+ "MusicRecognitionManagerService not defined by OEM or disabled by flag");
+ }
+
+
startContentCaptureService(context, t);
startAttentionService(context, t);
diff --git a/services/musicrecognition/Android.bp b/services/musicrecognition/Android.bp
new file mode 100644
index 0000000..39b5bb6
--- /dev/null
+++ b/services/musicrecognition/Android.bp
@@ -0,0 +1,13 @@
+filegroup {
+ name: "services.musicsearch-sources",
+ srcs: ["java/**/*.java"],
+ path: "java",
+ visibility: ["//frameworks/base/services"],
+}
+
+java_library_static {
+ name: "services.musicsearch",
+ defaults: ["services_defaults"],
+ srcs: [":services.musicsearch-sources"],
+ libs: ["services.core", "app-compat-annotations"],
+}
\ No newline at end of file
diff --git a/services/musicrecognition/java/com/android/server/musicrecognition/MusicRecognitionManagerPerUserService.java b/services/musicrecognition/java/com/android/server/musicrecognition/MusicRecognitionManagerPerUserService.java
new file mode 100644
index 0000000..e258ef0
--- /dev/null
+++ b/services/musicrecognition/java/com/android/server/musicrecognition/MusicRecognitionManagerPerUserService.java
@@ -0,0 +1,300 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.musicrecognition;
+
+import static android.media.musicrecognition.MusicRecognitionManager.RECOGNITION_FAILED_SERVICE_KILLED;
+import static android.media.musicrecognition.MusicRecognitionManager.RECOGNITION_FAILED_SERVICE_UNAVAILABLE;
+import static android.media.musicrecognition.MusicRecognitionManager.RecognitionFailureCode;
+
+import android.Manifest;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.AppGlobals;
+import android.content.ComponentName;
+import android.content.pm.PackageManager;
+import android.content.pm.ServiceInfo;
+import android.media.AudioRecord;
+import android.media.MediaMetadata;
+import android.media.musicrecognition.IMusicRecognitionManagerCallback;
+import android.media.musicrecognition.IMusicRecognitionServiceCallback;
+import android.media.musicrecognition.RecognitionRequest;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
+import android.util.Pair;
+import android.util.Slog;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.server.infra.AbstractPerUserSystemService;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * Handles per-user requests received by
+ * {@link MusicRecognitionManagerService}. Opens an audio stream from the
+ * dsp and writes it into a pipe to {@link RemoteMusicRecognitionService}.
+ */
+public final class MusicRecognitionManagerPerUserService extends
+ AbstractPerUserSystemService<MusicRecognitionManagerPerUserService,
+ MusicRecognitionManagerService>
+ implements RemoteMusicRecognitionService.Callbacks {
+
+ private static final String TAG = MusicRecognitionManagerPerUserService.class.getSimpleName();
+ // Number of bytes per sample of audio (which is a short).
+ private static final int BYTES_PER_SAMPLE = 2;
+ private static final int MAX_STREAMING_SECONDS = 24;
+
+ @Nullable
+ @GuardedBy("mLock")
+ private RemoteMusicRecognitionService mRemoteService;
+
+ private MusicRecognitionServiceCallback mRemoteServiceCallback =
+ new MusicRecognitionServiceCallback();
+ private IMusicRecognitionManagerCallback mCallback;
+
+ MusicRecognitionManagerPerUserService(
+ @NonNull MusicRecognitionManagerService primary,
+ @NonNull Object lock, int userId) {
+ super(primary, lock, userId);
+ }
+
+ @NonNull
+ @GuardedBy("mLock")
+ @Override
+ protected ServiceInfo newServiceInfoLocked(@NonNull ComponentName serviceComponent)
+ throws PackageManager.NameNotFoundException {
+ ServiceInfo si;
+ try {
+ si = AppGlobals.getPackageManager().getServiceInfo(serviceComponent,
+ PackageManager.GET_META_DATA, mUserId);
+ } catch (RemoteException e) {
+ throw new PackageManager.NameNotFoundException(
+ "Could not get service for " + serviceComponent);
+ }
+ if (!Manifest.permission.BIND_MUSIC_RECOGNITION_SERVICE.equals(si.permission)) {
+ Slog.w(TAG, "MusicRecognitionService from '" + si.packageName
+ + "' does not require permission "
+ + Manifest.permission.BIND_MUSIC_RECOGNITION_SERVICE);
+ throw new SecurityException("Service does not require permission "
+ + Manifest.permission.BIND_MUSIC_RECOGNITION_SERVICE);
+ }
+ // TODO(b/158194857): check process which owns the service has RECORD_AUDIO permission. How?
+ return si;
+ }
+
+ @GuardedBy("mLock")
+ @Nullable
+ private RemoteMusicRecognitionService ensureRemoteServiceLocked() {
+ if (mRemoteService == null) {
+ final String serviceName = getComponentNameLocked();
+ if (serviceName == null) {
+ if (mMaster.verbose) {
+ Slog.v(TAG, "ensureRemoteServiceLocked(): not set");
+ }
+ return null;
+ }
+ ComponentName serviceComponent = ComponentName.unflattenFromString(serviceName);
+
+ mRemoteService = new RemoteMusicRecognitionService(getContext(),
+ serviceComponent, mUserId, this,
+ mRemoteServiceCallback, mMaster.isBindInstantServiceAllowed(), mMaster.verbose);
+ }
+
+ return mRemoteService;
+ }
+
+ /**
+ * Read audio from the given capture session using an AudioRecord and writes it to a
+ * ParcelFileDescriptor.
+ */
+ @GuardedBy("mLock")
+ public void beginRecognitionLocked(
+ @NonNull RecognitionRequest recognitionRequest,
+ @NonNull IBinder callback) {
+ int maxAudioLengthSeconds = Math.min(recognitionRequest.getMaxAudioLengthSeconds(),
+ MAX_STREAMING_SECONDS);
+ mCallback = IMusicRecognitionManagerCallback.Stub.asInterface(callback);
+ AudioRecord audioRecord = createAudioRecord(recognitionRequest, maxAudioLengthSeconds);
+
+ mRemoteService = ensureRemoteServiceLocked();
+ if (mRemoteService == null) {
+ try {
+ mCallback.onRecognitionFailed(
+ RECOGNITION_FAILED_SERVICE_UNAVAILABLE);
+ } catch (RemoteException e) {
+ // Ignored.
+ }
+ return;
+ }
+
+ Pair<ParcelFileDescriptor, ParcelFileDescriptor> clientPipe = createPipe();
+ if (clientPipe == null) {
+ try {
+ mCallback.onAudioStreamClosed();
+ } catch (RemoteException ignored) {
+ // Ignored.
+ }
+ return;
+ }
+ ParcelFileDescriptor audioSink = clientPipe.second;
+ ParcelFileDescriptor clientRead = clientPipe.first;
+
+ mMaster.mExecutorService.execute(() -> {
+ try (OutputStream fos =
+ new ParcelFileDescriptor.AutoCloseOutputStream(audioSink)) {
+ int halfSecondBufferSize =
+ audioRecord.getBufferSizeInFrames() / maxAudioLengthSeconds;
+ byte[] byteBuffer = new byte[halfSecondBufferSize];
+ int bytesRead = 0;
+ int totalBytesRead = 0;
+ int ignoreBytes =
+ recognitionRequest.getIgnoreBeginningFrames() * BYTES_PER_SAMPLE;
+ audioRecord.startRecording();
+ while (bytesRead >= 0 && totalBytesRead
+ < audioRecord.getBufferSizeInFrames() * BYTES_PER_SAMPLE) {
+ bytesRead = audioRecord.read(byteBuffer, 0, byteBuffer.length);
+ if (bytesRead > 0) {
+ totalBytesRead += bytesRead;
+ // If we are ignoring the first x bytes, update that counter.
+ if (ignoreBytes > 0) {
+ ignoreBytes -= bytesRead;
+ // If we've dipped negative, we've skipped through all ignored bytes
+ // and then some. Write out the bytes we shouldn't have skipped.
+ if (ignoreBytes < 0) {
+ fos.write(byteBuffer, bytesRead + ignoreBytes, -ignoreBytes);
+ }
+ } else {
+ fos.write(byteBuffer);
+ }
+ }
+ }
+ Slog.i(TAG, String.format("Streamed %s bytes from audio record", totalBytesRead));
+ } catch (IOException e) {
+ Slog.e(TAG, "Audio streaming stopped.", e);
+ } finally {
+ audioRecord.release();
+ try {
+ mCallback.onAudioStreamClosed();
+ } catch (RemoteException ignored) {
+ // Ignored.
+ }
+
+ }
+ });
+ // Send the pipe down to the lookup service while we write to it asynchronously.
+ mRemoteService.writeAudioToPipe(clientRead, recognitionRequest.getAudioFormat());
+ }
+
+ /**
+ * Callback invoked by {@link android.service.musicrecognition.MusicRecognitionService} to pass
+ * back the music search result.
+ */
+ private final class MusicRecognitionServiceCallback extends
+ IMusicRecognitionServiceCallback.Stub {
+ @Override
+ public void onRecognitionSucceeded(MediaMetadata result, Bundle extras) {
+ try {
+ sanitizeBundle(extras);
+ mCallback.onRecognitionSucceeded(result, extras);
+ } catch (RemoteException ignored) {
+ // Ignored.
+ }
+ }
+
+ @Override
+ public void onRecognitionFailed(@RecognitionFailureCode int failureCode) {
+ try {
+ mCallback.onRecognitionFailed(failureCode);
+ } catch (RemoteException ignored) {
+ // Ignored.
+ }
+ }
+ }
+
+ @Override
+ public void onServiceDied(@NonNull RemoteMusicRecognitionService service) {
+ try {
+ mCallback.onRecognitionFailed(RECOGNITION_FAILED_SERVICE_KILLED);
+ } catch (RemoteException e) {
+ // Ignored.
+ }
+ Slog.w(TAG, "remote service died: " + service);
+ }
+
+ /** Establishes an audio stream from the DSP audio source. */
+ private static AudioRecord createAudioRecord(
+ @NonNull RecognitionRequest recognitionRequest,
+ int maxAudioLengthSeconds) {
+ int sampleRate = recognitionRequest.getAudioFormat().getSampleRate();
+ int bufferSize = getBufferSizeInBytes(sampleRate, maxAudioLengthSeconds);
+ return new AudioRecord(recognitionRequest.getAudioAttributes(),
+ recognitionRequest.getAudioFormat(), bufferSize,
+ recognitionRequest.getCaptureSession());
+ }
+
+ /**
+ * Returns the number of bytes required to store {@code bufferLengthSeconds} of audio sampled at
+ * {@code sampleRate} Hz, using the format returned by DSP audio capture.
+ */
+ private static int getBufferSizeInBytes(int sampleRate, int bufferLengthSeconds) {
+ return BYTES_PER_SAMPLE * sampleRate * bufferLengthSeconds;
+ }
+
+ private static Pair<ParcelFileDescriptor, ParcelFileDescriptor> createPipe() {
+ ParcelFileDescriptor[] fileDescriptors;
+ try {
+ fileDescriptors = ParcelFileDescriptor.createPipe();
+ } catch (IOException e) {
+ Slog.e(TAG, "Failed to create audio stream pipe", e);
+ return null;
+ }
+
+ if (fileDescriptors.length != 2) {
+ Slog.e(TAG, "Failed to create audio stream pipe, "
+ + "unexpected number of file descriptors");
+ return null;
+ }
+
+ if (!fileDescriptors[0].getFileDescriptor().valid()
+ || !fileDescriptors[1].getFileDescriptor().valid()) {
+ Slog.e(TAG, "Failed to create audio stream pipe, didn't "
+ + "receive a pair of valid file descriptors.");
+ return null;
+ }
+
+ return Pair.create(fileDescriptors[0], fileDescriptors[1]);
+ }
+
+ /** Removes remote objects from the bundle. */
+ private static void sanitizeBundle(@Nullable Bundle bundle) {
+ if (bundle == null) {
+ return;
+ }
+
+ for (String key : bundle.keySet()) {
+ Object o = bundle.get(key);
+
+ if (o instanceof Bundle) {
+ sanitizeBundle((Bundle) o);
+ } else if (o instanceof IBinder || o instanceof ParcelFileDescriptor) {
+ bundle.remove(key);
+ }
+ }
+ }
+}
diff --git a/services/musicrecognition/java/com/android/server/musicrecognition/MusicRecognitionManagerService.java b/services/musicrecognition/java/com/android/server/musicrecognition/MusicRecognitionManagerService.java
new file mode 100644
index 0000000..b4cb337
--- /dev/null
+++ b/services/musicrecognition/java/com/android/server/musicrecognition/MusicRecognitionManagerService.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.musicrecognition;
+
+import static android.content.PermissionChecker.PERMISSION_GRANTED;
+import static android.media.musicrecognition.MusicRecognitionManager.RECOGNITION_FAILED_SERVICE_UNAVAILABLE;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.media.musicrecognition.IMusicRecognitionManager;
+import android.media.musicrecognition.IMusicRecognitionManagerCallback;
+import android.media.musicrecognition.RecognitionRequest;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.UserHandle;
+
+import com.android.server.infra.AbstractMasterSystemService;
+import com.android.server.infra.FrameworkResourcesServiceNameResolver;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * Service which allows a DSP audio event to be securely streamed to a designated {@link
+ * MusicRecognitionService}.
+ */
+public class MusicRecognitionManagerService extends
+ AbstractMasterSystemService<MusicRecognitionManagerService,
+ MusicRecognitionManagerPerUserService> {
+
+ private static final String TAG = MusicRecognitionManagerService.class.getSimpleName();
+
+ private MusicRecognitionManagerStub mMusicRecognitionManagerStub;
+ final ExecutorService mExecutorService = Executors.newCachedThreadPool();
+
+ /**
+ * Initializes the system service.
+ *
+ * Subclasses must define a single argument constructor that accepts the context
+ * and passes it to super.
+ *
+ * @param context The system server context.
+ */
+ public MusicRecognitionManagerService(@NonNull Context context) {
+ super(context, new FrameworkResourcesServiceNameResolver(context,
+ com.android.internal.R.string.config_defaultMusicRecognitionService),
+ /** disallowProperty */null);
+ }
+
+ @Nullable
+ @Override
+ protected MusicRecognitionManagerPerUserService newServiceLocked(int resolvedUserId,
+ boolean disabled) {
+ return new MusicRecognitionManagerPerUserService(this, mLock, resolvedUserId);
+ }
+
+ @Override
+ public void onStart() {
+ mMusicRecognitionManagerStub = new MusicRecognitionManagerStub();
+ publishBinderService(Context.MUSIC_RECOGNITION_SERVICE, mMusicRecognitionManagerStub);
+ }
+
+ private void enforceCaller(String func) {
+ Context ctx = getContext();
+ if (ctx.checkCallingPermission(android.Manifest.permission.MANAGE_MUSIC_RECOGNITION)
+ == PERMISSION_GRANTED) {
+ return;
+ }
+
+ String msg = "Permission Denial: " + func + " from pid="
+ + Binder.getCallingPid()
+ + ", uid=" + Binder.getCallingUid()
+ + " doesn't hold " + android.Manifest.permission.MANAGE_MUSIC_RECOGNITION;
+ throw new SecurityException(msg);
+ }
+
+ final class MusicRecognitionManagerStub extends IMusicRecognitionManager.Stub {
+ @Override
+ public void beginRecognition(
+ @NonNull RecognitionRequest recognitionRequest,
+ @NonNull IBinder callback) {
+ enforceCaller("beginRecognition");
+
+ synchronized (mLock) {
+ final MusicRecognitionManagerPerUserService service = getServiceForUserLocked(
+ UserHandle.getCallingUserId());
+ if (service != null) {
+ service.beginRecognitionLocked(recognitionRequest, callback);
+ } else {
+ try {
+ IMusicRecognitionManagerCallback.Stub.asInterface(callback)
+ .onRecognitionFailed(RECOGNITION_FAILED_SERVICE_UNAVAILABLE);
+ } catch (RemoteException e) {
+ // ignored.
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/services/musicrecognition/java/com/android/server/musicrecognition/RemoteMusicRecognitionService.java b/services/musicrecognition/java/com/android/server/musicrecognition/RemoteMusicRecognitionService.java
new file mode 100644
index 0000000..4814a82
--- /dev/null
+++ b/services/musicrecognition/java/com/android/server/musicrecognition/RemoteMusicRecognitionService.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.musicrecognition;
+
+import android.annotation.NonNull;
+import android.content.ComponentName;
+import android.content.Context;
+import android.media.AudioFormat;
+import android.media.musicrecognition.IMusicRecognitionService;
+import android.media.musicrecognition.IMusicRecognitionServiceCallback;
+import android.media.musicrecognition.MusicRecognitionService;
+import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
+import android.text.format.DateUtils;
+
+import com.android.internal.infra.AbstractMultiplePendingRequestsRemoteService;
+
+/** Remote connection to an instance of {@link MusicRecognitionService}. */
+public class RemoteMusicRecognitionService extends
+ AbstractMultiplePendingRequestsRemoteService<RemoteMusicRecognitionService,
+ IMusicRecognitionService> {
+
+ // Maximum time allotted for the remote service to return a result. Up to 24s of audio plus
+ // time to fingerprint and make rpcs.
+ private static final long TIMEOUT_IDLE_BIND_MILLIS = 40 * DateUtils.SECOND_IN_MILLIS;
+
+ // Allows the remote service to send back a result.
+ private final IMusicRecognitionServiceCallback mServerCallback;
+
+ public RemoteMusicRecognitionService(Context context, ComponentName serviceName,
+ int userId, MusicRecognitionManagerPerUserService perUserService,
+ IMusicRecognitionServiceCallback callback,
+ boolean bindInstantServiceAllowed, boolean verbose) {
+ super(context, MusicRecognitionService.ACTION_MUSIC_SEARCH_LOOKUP, serviceName, userId,
+ perUserService,
+ context.getMainThreadHandler(),
+ // Prevents the service from having its permissions stripped while in background.
+ Context.BIND_INCLUDE_CAPABILITIES | (bindInstantServiceAllowed
+ ? Context.BIND_ALLOW_INSTANT : 0), verbose,
+ /* initialCapacity= */ 1);
+ mServerCallback = callback;
+ }
+
+ @NonNull
+ @Override
+ protected IMusicRecognitionService getServiceInterface(@NonNull IBinder service) {
+ return IMusicRecognitionService.Stub.asInterface(service);
+ }
+
+ @Override
+ protected long getTimeoutIdleBindMillis() {
+ return TIMEOUT_IDLE_BIND_MILLIS;
+ }
+
+ /**
+ * Required, but empty since we don't need to notify the callback implementation of the request
+ * results.
+ */
+ interface Callbacks extends VultureCallback<RemoteMusicRecognitionService> {}
+
+ /**
+ * Sends the given descriptor to the app's {@link MusicRecognitionService} to read the
+ * audio.
+ */
+ public void writeAudioToPipe(@NonNull ParcelFileDescriptor fd,
+ @NonNull AudioFormat audioFormat) {
+ scheduleAsyncRequest(
+ binder -> binder.onAudioStreamStarted(fd, audioFormat, mServerCallback));
+ }
+}
diff --git a/services/net/java/android/net/TcpKeepalivePacketData.java b/services/net/java/android/net/TcpKeepalivePacketData.java
index c0c386b..4875c7c 100644
--- a/services/net/java/android/net/TcpKeepalivePacketData.java
+++ b/services/net/java/android/net/TcpKeepalivePacketData.java
@@ -19,11 +19,12 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.net.util.IpUtils;
import android.os.Parcel;
import android.os.Parcelable;
import android.system.OsConstants;
+import com.android.net.module.util.IpUtils;
+
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
diff --git a/services/profcollect/Android.bp b/services/profcollect/Android.bp
index 68fba55..b7be5d4 100644
--- a/services/profcollect/Android.bp
+++ b/services/profcollect/Android.bp
@@ -30,6 +30,7 @@
java_library_static {
name: "services.profcollect",
+ defaults: ["services_defaults"],
srcs: [":services.profcollect-sources"],
libs: ["services.core"],
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/AppChildProcessTest.java b/services/tests/mockingservicestests/src/com/android/server/am/AppChildProcessTest.java
index 04e8b63..b85da94 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/AppChildProcessTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/AppChildProcessTest.java
@@ -34,12 +34,12 @@
import android.os.HandlerThread;
import android.os.Process;
import android.platform.test.annotations.Presubmit;
+import android.util.ArrayMap;
import android.util.ArraySet;
import com.android.dx.mockito.inline.extended.StaticMockitoSession;
import com.android.server.LocalServices;
import com.android.server.ServiceThread;
-import com.android.server.am.ActivityManagerService.Injector;
import com.android.server.appop.AppOpsService;
import com.android.server.wm.ActivityTaskManagerService;
@@ -55,7 +55,11 @@
import org.mockito.MockitoAnnotations;
import org.mockito.quality.Strictness;
+import java.io.ByteArrayInputStream;
import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
@Presubmit
public class AppChildProcessTest {
@@ -68,6 +72,7 @@
private Context mContext = getInstrumentation().getTargetContext();
private TestInjector mInjector;
+ private PhantomTestInjector mPhantomInjector;
private ActivityManagerService mAms;
private ProcessList mProcessList;
private PhantomProcessList mPhantomProcessList;
@@ -94,6 +99,7 @@
mProcessList = spy(pList);
mInjector = new TestInjector(mContext);
+ mPhantomInjector = new PhantomTestInjector();
mAms = new ActivityManagerService(mInjector, mServiceThreadRule.getThread());
mAms.mActivityTaskManager = new ActivityTaskManagerService(mContext);
mAms.mActivityTaskManager.initialize(null, null, mContext.getMainLooper());
@@ -101,6 +107,7 @@
mAms.mPackageManagerInt = mPackageManagerInt;
pList.mService = mAms;
mPhantomProcessList = mAms.mPhantomProcessList;
+ mPhantomProcessList.mInjector = mPhantomInjector;
doReturn(new ComponentName("", "")).when(mPackageManagerInt).getSystemUiServiceComponent();
doReturn(false).when(() -> Process.supportsPidFd());
// Remove stale instance of PackageManagerInternal if there is any
@@ -136,47 +143,60 @@
final String child2ProcessName = "test1_child1_child2";
final String nativeProcessName = "test_native";
- makeParent(zygote64Pid, initPid);
- makeParent(zygote32Pid, initPid);
+ makeProcess(rootUid, zygote64Pid, zygote64ProcessName);
+ makeParent(rootUid, zygote64Pid, initPid);
+ makeProcess(rootUid, zygote32Pid, zygote32ProcessName);
+ makeParent(rootUid, zygote32Pid, initPid);
makeAppProcess(app1Pid, app1Uid, app1ProcessName, app1ProcessName);
- makeParent(app1Pid, zygote64Pid);
makeAppProcess(app2Pid, app2Uid, app2ProcessName, app2ProcessName);
- makeParent(app2Pid, zygote64Pid);
+
+ mPhantomProcessList.lookForPhantomProcessesLocked();
assertEquals(0, mPhantomProcessList.mPhantomProcesses.size());
// Verify zygote itself isn't a phantom process
assertEquals(null, mPhantomProcessList.getOrCreatePhantomProcessIfNeededLocked(
- zygote64ProcessName, rootUid, zygote64Pid));
+ zygote64ProcessName, rootUid, zygote64Pid, false));
assertEquals(null, mPhantomProcessList.getOrCreatePhantomProcessIfNeededLocked(
- zygote32ProcessName, rootUid, zygote32Pid));
+ zygote32ProcessName, rootUid, zygote32Pid, false));
// Verify none of the app isn't a phantom process
assertEquals(null, mPhantomProcessList.getOrCreatePhantomProcessIfNeededLocked(
- app1ProcessName, app1Uid, app1Pid));
+ app1ProcessName, app1Uid, app1Pid, false));
assertEquals(null, mPhantomProcessList.getOrCreatePhantomProcessIfNeededLocked(
- app2ProcessName, app2Uid, app2Pid));
+ app2ProcessName, app2Uid, app2Pid, false));
// "Fork" an app child process
- makeParent(child1Pid, app1Pid);
+ makeProcess(app1Uid, child1Pid, child1ProcessName);
+ makeParent(app1Uid, child1Pid, app1Pid);
+ mPhantomProcessList.lookForPhantomProcessesLocked();
+
PhantomProcessRecord pr = mPhantomProcessList
- .getOrCreatePhantomProcessIfNeededLocked(child1ProcessName, app1Uid, child1Pid);
+ .getOrCreatePhantomProcessIfNeededLocked(
+ child1ProcessName, app1Uid, child1Pid, true);
assertTrue(pr != null);
assertEquals(1, mPhantomProcessList.mPhantomProcesses.size());
assertEquals(pr, mPhantomProcessList.mPhantomProcesses.valueAt(0));
verifyPhantomProcessRecord(pr, child1ProcessName, app1Uid, child1Pid);
// Create another native process from init
- makeParent(nativePid, initPid);
+ makeProcess(rootUid, nativePid, nativeProcessName);
+ makeParent(rootUid, nativePid, initPid);
+ mPhantomProcessList.lookForPhantomProcessesLocked();
+
assertEquals(null, mPhantomProcessList.getOrCreatePhantomProcessIfNeededLocked(
- nativeProcessName, rootUid, nativePid));
+ nativeProcessName, rootUid, nativePid, false));
assertEquals(1, mPhantomProcessList.mPhantomProcesses.size());
assertEquals(pr, mPhantomProcessList.mPhantomProcesses.valueAt(0));
// "Fork" another app child process
- makeParent(child2Pid, child1Pid);
+ makeProcess(app1Uid, child2Pid, child2ProcessName);
+ makeParent(app1Uid, child2Pid, app1Pid);
+ mPhantomProcessList.lookForPhantomProcessesLocked();
+
PhantomProcessRecord pr2 = mPhantomProcessList
- .getOrCreatePhantomProcessIfNeededLocked(child2ProcessName, app1Uid, child2Pid);
+ .getOrCreatePhantomProcessIfNeededLocked(
+ child2ProcessName, app1Uid, child2Pid, false);
assertTrue(pr2 != null);
assertEquals(2, mPhantomProcessList.mPhantomProcesses.size());
verifyPhantomProcessRecord(pr2, child2ProcessName, app1Uid, child2Pid);
@@ -197,19 +217,27 @@
assertEquals(pid, pr.mPid);
}
+ private void makeProcess(int uid, int pid, String processName) {
+ doReturn(uid).when(() -> Process.getUidForPid(eq(pid)));
+ mPhantomInjector.mPidToName.put(pid, processName);
+ }
+
private void makeAppProcess(int pid, int uid, String packageName, String processName) {
+ makeProcess(uid, pid, processName);
ApplicationInfo ai = new ApplicationInfo();
ai.packageName = packageName;
+ ai.uid = uid;
ProcessRecord app = new ProcessRecord(mAms, ai, processName, uid);
app.pid = pid;
mAms.mPidsSelfLocked.doAddInternal(app);
+ mPhantomInjector.addToProcess(uid, pid, pid);
}
- private void makeParent(int pid, int ppid) {
- doReturn(ppid).when(() -> Process.getParentPid(eq(pid)));
+ private void makeParent(int uid, int pid, int ppid) {
+ mPhantomInjector.addToProcess(uid, ppid, pid);
}
- private class TestInjector extends Injector {
+ private class TestInjector extends ActivityManagerService.Injector {
TestInjector(Context context) {
super(context);
}
@@ -230,6 +258,56 @@
}
}
+ private class PhantomTestInjector extends PhantomProcessList.Injector {
+ ArrayMap<String, InputStream> mPathToInput = new ArrayMap<>();
+ ArrayMap<String, StringBuffer> mPathToData = new ArrayMap<>();
+ ArrayMap<InputStream, StringBuffer> mInputToData = new ArrayMap<>();
+ ArrayMap<Integer, String> mPidToName = new ArrayMap<>();
+
+ @Override
+ InputStream openCgroupProcs(String path) throws FileNotFoundException, SecurityException {
+ InputStream input = mPathToInput.get(path);
+ if (input != null) {
+ return input;
+ }
+ input = new ByteArrayInputStream(new byte[8]); // buf size doesn't matter here
+ mPathToInput.put(path, input);
+ StringBuffer sb = mPathToData.get(path);
+ if (sb == null) {
+ sb = new StringBuffer();
+ mPathToData.put(path, sb);
+ }
+ mInputToData.put(input, sb);
+ return input;
+ }
+
+ @Override
+ int readCgroupProcs(InputStream input, byte[] buf, int offset, int len) throws IOException {
+ StringBuffer sb = mInputToData.get(input);
+ if (sb == null) {
+ return -1;
+ }
+ byte[] avail = sb.toString().getBytes();
+ System.arraycopy(avail, 0, buf, offset, Math.min(len, avail.length));
+ return Math.min(len, avail.length);
+ }
+
+ @Override
+ String getProcessName(final int pid) {
+ return mPidToName.get(pid);
+ }
+
+ void addToProcess(int uid, int pid, int newPid) {
+ final String path = PhantomProcessList.getCgroupFilePath(uid, pid);
+ StringBuffer sb = mPathToData.get(path);
+ if (sb == null) {
+ sb = new StringBuffer();
+ mPathToData.put(path, sb);
+ }
+ sb.append(newPid).append('\n');
+ }
+ }
+
static class ServiceThreadRule implements TestRule {
private ServiceThread mThread;
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/HardwareAuthTokenUtilsTest.java b/services/tests/servicestests/src/com/android/server/biometrics/HardwareAuthTokenUtilsTest.java
new file mode 100644
index 0000000..84987e6
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/biometrics/HardwareAuthTokenUtilsTest.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.biometrics;
+
+import static junit.framework.Assert.assertEquals;
+
+import android.hardware.keymaster.HardwareAuthToken;
+import android.hardware.keymaster.Timestamp;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+
+@Presubmit
+@SmallTest
+public class HardwareAuthTokenUtilsTest {
+
+ @Test
+ public void testByteArrayLoopBack() {
+ final byte[] hat = new byte[69];
+ for (int i = 0; i < 69; i++) {
+ hat[i] = (byte) i;
+ }
+
+ final HardwareAuthToken hardwareAuthToken = HardwareAuthTokenUtils.toHardwareAuthToken(hat);
+ final byte[] hat2 = HardwareAuthTokenUtils.toByteArray(hardwareAuthToken);
+
+ for (int i = 0; i < hat.length; i++) {
+ assertEquals(hat[i], hat2[i]);
+ }
+ }
+
+ @Test
+ public void testHardwareAuthTokenLoopBack() {
+ final long testChallenge = 1000L;
+ final long testUserId = 2000L;
+ final long testAuthenticatorId = 3000L;
+ final int testAuthenticatorType = 4000;
+ final long testTimestamp = 5000L;
+
+ final HardwareAuthToken hardwareAuthToken = new HardwareAuthToken();
+ hardwareAuthToken.challenge = testChallenge;
+ hardwareAuthToken.userId = testUserId;
+ hardwareAuthToken.authenticatorId = testAuthenticatorId;
+ hardwareAuthToken.authenticatorType = testAuthenticatorType;
+ hardwareAuthToken.timestamp = new Timestamp();
+ hardwareAuthToken.timestamp.milliSeconds = testTimestamp;
+ hardwareAuthToken.mac = new byte[32];
+
+ for (int i = 0; i < hardwareAuthToken.mac.length; i++) {
+ hardwareAuthToken.mac[i] = (byte) i;
+ }
+
+ final byte[] hat = HardwareAuthTokenUtils.toByteArray(hardwareAuthToken);
+ final HardwareAuthToken hardwareAuthToken2 =
+ HardwareAuthTokenUtils.toHardwareAuthToken(hat);
+
+ assertEquals(testChallenge, hardwareAuthToken2.challenge);
+ assertEquals(testUserId, hardwareAuthToken2.userId);
+ assertEquals(testAuthenticatorId, hardwareAuthToken2.authenticatorId);
+ assertEquals(testAuthenticatorType, hardwareAuthToken2.authenticatorType);
+ assertEquals(testTimestamp, hardwareAuthToken2.timestamp.milliSeconds);
+
+ for (int i = 0; i < hardwareAuthToken.mac.length; i++) {
+ assertEquals(hardwareAuthToken.mac[i], hardwareAuthToken2.mac[i]);
+ }
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/ConfigurationInternalTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/ConfigurationInternalTest.java
index 54b5bee..3fc294d 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/ConfigurationInternalTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/ConfigurationInternalTest.java
@@ -91,7 +91,7 @@
TimeZoneCapabilities capabilities = capabilitiesAndConfig.getCapabilities();
assertEquals(CAPABILITY_POSSESSED,
capabilities.getConfigureAutoDetectionEnabledCapability());
- assertEquals(CAPABILITY_POSSESSED,
+ assertEquals(CAPABILITY_NOT_APPLICABLE,
capabilities.getConfigureGeoDetectionEnabledCapability());
assertEquals(CAPABILITY_POSSESSED,
capabilities.getSuggestManualTimeZoneCapability());
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
index d7e431f..e304083 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
@@ -690,6 +690,39 @@
}
@Test
+ public void unbindOtherUserServices() throws PackageManager.NameNotFoundException {
+ Context context = mock(Context.class);
+ PackageManager pm = mock(PackageManager.class);
+ ApplicationInfo ai = new ApplicationInfo();
+ ai.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
+
+ when(context.getPackageName()).thenReturn(mContext.getPackageName());
+ when(context.getUserId()).thenReturn(mContext.getUserId());
+ when(context.getPackageManager()).thenReturn(pm);
+ when(pm.getApplicationInfo(anyString(), anyInt())).thenReturn(ai);
+
+ ManagedServices service = new TestManagedServices(context, mLock, mUserProfiles, mIpm,
+ APPROVAL_BY_COMPONENT);
+ ComponentName cn = ComponentName.unflattenFromString("a/a");
+
+ when(context.bindServiceAsUser(any(), any(), anyInt(), any())).thenAnswer(invocation -> {
+ Object[] args = invocation.getArguments();
+ ServiceConnection sc = (ServiceConnection) args[1];
+ sc.onServiceConnected(cn, mock(IBinder.class));
+ return true;
+ });
+
+ service.registerService(cn, 0);
+ service.registerService(cn, 10);
+ service.registerService(cn, 11);
+ service.unbindOtherUserServices(11);
+
+ assertFalse(service.isBound(cn, 0));
+ assertFalse(service.isBound(cn, 10));
+ assertTrue(service.isBound(cn, 11));
+ }
+
+ @Test
public void testPackageUninstall_packageNoLongerInApprovedList() throws Exception {
for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
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 e45b28e..4d0d3b2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -1584,6 +1584,28 @@
assertFalse(publicDc.forceDesktopMode());
}
+ @Test
+ public void testDisplaySettingsReappliedWhenDisplayChanged() {
+ final DisplayInfo displayInfo = new DisplayInfo();
+ displayInfo.copyFrom(mDisplayInfo);
+ final DisplayContent dc = createNewDisplay(displayInfo);
+
+ // Generate width/height/density values different from the default of the display.
+ final int forcedWidth = dc.mBaseDisplayWidth + 1;
+ final int forcedHeight = dc.mBaseDisplayHeight + 1;;
+ final int forcedDensity = dc.mBaseDisplayDensity + 1;;
+ // Update the forced size and density in settings and the unique id to simualate a display
+ // remap.
+ dc.mWmService.mDisplayWindowSettings.setForcedSize(dc, forcedWidth, forcedHeight);
+ dc.mWmService.mDisplayWindowSettings.setForcedDensity(dc, forcedDensity, 0 /* userId */);
+ dc.mCurrentUniqueDisplayId = mDisplayInfo.uniqueId + "-test";
+ // Trigger display changed.
+ dc.onDisplayChanged();
+ // Ensure overridden size and denisty match the most up-to-date values in settings for the
+ // display.
+ verifySizes(dc, forcedWidth, forcedHeight, forcedDensity);
+ }
+
private boolean isOptionsPanelAtRight(int displayId) {
return (mWm.getPreferredOptionsPanelGravity(displayId) & Gravity.RIGHT) == Gravity.RIGHT;
}
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index a6d7245..9f16543 100755
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -966,6 +966,32 @@
/**
* Gets the verification status for the phone number of an incoming call as identified in
* ATIS-1000082.
+ * <p>
+ * For incoming calls, the number verification status indicates whether the device was
+ * able to verify the authenticity of the calling number using the STIR process outlined
+ * in ATIS-1000082. {@link Connection#VERIFICATION_STATUS_NOT_VERIFIED} indicates that
+ * the network was not able to use STIR to verify the caller's number (i.e. nothing is
+ * known regarding the authenticity of the number.
+ * {@link Connection#VERIFICATION_STATUS_PASSED} indicates that the network was able to
+ * use STIR to verify the caller's number. This indicates that the network has a high
+ * degree of confidence that the incoming call actually originated from the indicated
+ * number. {@link Connection#VERIFICATION_STATUS_FAILED} indicates that the network's
+ * STIR verification did not pass. This indicates that the incoming call may not
+ * actually be from the indicated number. This could occur if, for example, the caller
+ * is using an impersonated phone number.
+ * <p>
+ * A {@link CallScreeningService} can use this information to help determine if an
+ * incoming call is potentially an unwanted call. A verification status of
+ * {@link Connection#VERIFICATION_STATUS_FAILED} indicates that an incoming call may not
+ * actually be from the number indicated on the call (i.e. impersonated number) and that it
+ * should potentially be blocked. Likewise,
+ * {@link Connection#VERIFICATION_STATUS_PASSED} can be used as a positive signal to
+ * help clarify that the incoming call is originating from the indicated number and it
+ * is less likely to be an undesirable call.
+ * <p>
+ * An {@link InCallService} can use this information to provide a visual indicator to the
+ * user regarding the verification status of a call and to help identify calls from
+ * potentially impersonated numbers.
* @return the verification status.
*/
public @Connection.VerificationStatus int getCallerNumberVerificationStatus() {
diff --git a/telephony/api/system-current.txt b/telephony/api/system-current.txt
index af5badd..11fae0c 100644
--- a/telephony/api/system-current.txt
+++ b/telephony/api/system-current.txt
@@ -727,6 +727,7 @@
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean isIccLockEnabled();
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isIdle();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isLteCdmaEvdoGsmWcdmaEnabled();
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isMobileDataPolicyEnabled(int);
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isOffhook();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isOpportunisticNetworkEnabled();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isPotentialEmergencyNumber(@NonNull String);
@@ -757,6 +758,7 @@
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataActivationState(int);
method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataEnabled(int, boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataRoamingEnabled(boolean);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setMobileDataPolicyEnabledStatus(int, boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setMultiSimCarrierRestriction(boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setOpportunisticNetworkState(boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setPreferredNetworkTypeBitmask(long);
@@ -807,6 +809,8 @@
field public static final int INVALID_EMERGENCY_NUMBER_DB_VERSION = -1; // 0xffffffff
field public static final int KEY_TYPE_EPDG = 1; // 0x1
field public static final int KEY_TYPE_WLAN = 2; // 0x2
+ field public static final int MOBILE_DATA_POLICY_DATA_ON_NON_DEFAULT_DURING_VOICE_CALL = 1; // 0x1
+ field public static final int MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED = 2; // 0x2
field public static final long NETWORK_TYPE_BITMASK_1xRTT = 64L; // 0x40L
field public static final long NETWORK_TYPE_BITMASK_CDMA = 8L; // 0x8L
field public static final long NETWORK_TYPE_BITMASK_EDGE = 2L; // 0x2L
diff --git a/telephony/java/android/telephony/BinderCacheManager.java b/telephony/java/android/telephony/BinderCacheManager.java
new file mode 100644
index 0000000..0d3e2fe7
--- /dev/null
+++ b/telephony/java/android/telephony/BinderCacheManager.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony;
+
+import android.annotation.NonNull;
+import android.os.IBinder;
+import android.os.IInterface;
+import android.os.RemoteException;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.NoSuchElementException;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * Keeps track of the connection to a Binder node, refreshes the cache if the node dies, and lets
+ * interested parties register listeners on the node to be notified when the node has died via the
+ * registered {@link Runnable}.
+ * @param <T> The IInterface representing the Binder type that this manager will be managing the
+ * cache of.
+ * @hide
+ */
+public class BinderCacheManager<T extends IInterface> {
+
+ /**
+ * Factory class for creating new IInterfaces in the case that {@link #getBinder()} is
+ * called and there is no active binder available.
+ * @param <T> The IInterface that should be cached and returned to the caller when
+ * {@link #getBinder()} is called until the Binder node dies.
+ */
+ public interface BinderInterfaceFactory<T> {
+ /**
+ * @return A new instance of the Binder node, which will be cached until it dies.
+ */
+ T create();
+ }
+
+ /**
+ * Tracks the cached Binder node as well as the listeners that were associated with that
+ * Binder node during its lifetime. If the Binder node dies, the listeners will be called and
+ * then this tracker will be unlinked and cleaned up.
+ */
+ private class BinderDeathTracker implements IBinder.DeathRecipient {
+
+ private final T mConnection;
+ private final HashMap<Object, Runnable> mListeners = new HashMap<>();
+
+ /**
+ * Create a tracker to cache the Binder node and add the ability to listen for the cached
+ * interface's death.
+ */
+ BinderDeathTracker(@NonNull T connection) {
+ mConnection = connection;
+ try {
+ mConnection.asBinder().linkToDeath(this, 0 /*flags*/);
+ } catch (RemoteException e) {
+ // isAlive will return false.
+ }
+ }
+
+ public boolean addListener(Object key, Runnable r) {
+ synchronized (mListeners) {
+ if (!isAlive()) return false;
+ mListeners.put(key, r);
+ return true;
+ }
+ }
+
+ public void removeListener(Object runnableKey) {
+ synchronized (mListeners) {
+ mListeners.remove(runnableKey);
+ }
+ }
+
+ @Override
+ public void binderDied() {
+ ArrayList<Runnable> listeners;
+ synchronized (mListeners) {
+ listeners = new ArrayList<>(mListeners.values());
+ mListeners.clear();
+ try {
+ mConnection.asBinder().unlinkToDeath(this, 0 /*flags*/);
+ } catch (NoSuchElementException e) {
+ // No need to worry about this, this means the death recipient was never linked.
+ }
+ }
+ listeners.forEach(Runnable::run);
+ }
+
+ /**
+ * @return The cached Binder.
+ */
+ public T getConnection() {
+ return mConnection;
+ }
+
+ /**
+ * @return true if the cached Binder is alive at the time of calling, false otherwise.
+ */
+ public boolean isAlive() {
+ return mConnection.asBinder().isBinderAlive();
+ }
+ }
+
+ private final BinderInterfaceFactory<T> mBinderInterfaceFactory;
+ private final AtomicReference<BinderDeathTracker> mCachedConnection;
+
+ /**
+ * Create a new instance, which manages a cached IInterface and creates new ones using the
+ * provided factory when the cached IInterface dies.
+ * @param factory The factory used to create new Instances of the cached IInterface when it
+ * dies.
+ */
+ public BinderCacheManager(BinderInterfaceFactory<T> factory) {
+ mBinderInterfaceFactory = factory;
+ mCachedConnection = new AtomicReference<>();
+ }
+
+ /**
+ * Get the binder node connection and add a Runnable to be run if this Binder dies. Once this
+ * Runnable is run, the Runnable itself is discarded and must be added again.
+ * <p>
+ * Note: There should be no assumptions here as to which Thread this Runnable is called on. If
+ * the Runnable should be called on a specific thread, it should be up to the caller to handle
+ * that in the runnable implementation.
+ * @param runnableKey The Key associated with this runnable so that it can be removed later
+ * using {@link #removeRunnable(Object)} if needed.
+ * @param deadRunnable The runnable that will be run if the cached Binder node dies.
+ * @return T if the runnable was added or {@code null} if the connection is not alive right now
+ * and the associated runnable was never added.
+ */
+ public T listenOnBinder(Object runnableKey, Runnable deadRunnable) {
+ if (runnableKey == null || deadRunnable == null) return null;
+ BinderDeathTracker tracker = getTracker();
+ if (tracker == null) return null;
+
+ boolean addSucceeded = tracker.addListener(runnableKey, deadRunnable);
+ return addSucceeded ? tracker.getConnection() : null;
+ }
+
+ /**
+ * @return The cached Binder node. May return null if the requested Binder node is not currently
+ * available.
+ */
+ public T getBinder() {
+ BinderDeathTracker tracker = getTracker();
+ return (tracker != null) ? tracker.getConnection() : null;
+ }
+
+ /**
+ * Removes a previously registered runnable associated with the returned cached Binder node
+ * using the key it was registered with in {@link #listenOnBinder} if the runnable still exists.
+ * @param runnableKey The key that was used to register the Runnable earlier.
+ * @return The cached Binder node that the runnable used to registered to or null if the cached
+ * Binder node is not alive anymore.
+ */
+ public T removeRunnable(Object runnableKey) {
+ if (runnableKey == null) return null;
+ BinderDeathTracker tracker = getTracker();
+ if (tracker == null) return null;
+ tracker.removeListener(runnableKey);
+ return tracker.getConnection();
+ }
+
+ /**
+ * @return The BinderDeathTracker container, which contains the cached IInterface instance or
+ * null if it is not available right now.
+ */
+ private BinderDeathTracker getTracker() {
+ return mCachedConnection.updateAndGet((oldVal) -> {
+ BinderDeathTracker tracker = oldVal;
+ // Update cache if no longer alive. BinderDied will eventually be called on the tracker,
+ // which will call listeners & clean up.
+ if (tracker == null || !tracker.isAlive()) {
+ T binder = mBinderInterfaceFactory.create();
+ tracker = (binder != null) ? new BinderDeathTracker(binder) : null;
+
+ }
+ return (tracker != null && tracker.isAlive()) ? tracker : null;
+ });
+ }
+
+}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 12e56cc..ceaa425 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -12808,7 +12808,7 @@
* 1) User data is turned on, or
* 2) APN is un-metered for this subscription, or
* 3) APN type is whitelisted. E.g. MMS is whitelisted if
- * {@link #setAlwaysAllowMmsData(boolean)} is turned on.
+ * {@link #MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED} is enabled.
*
* @param apnType Value indicating the apn type. Apn types are defined in {@link ApnSetting}.
* @return whether data is enabled for a apn type.
@@ -13285,26 +13285,66 @@
}
/**
- * Set allowing mobile data during voice call. This is used for allowing data on the non-default
- * data SIM. When a voice call is placed on the non-default data SIM on DSDS devices, users will
- * not be able to use mobile data. By calling this API, data will be temporarily enabled on the
- * non-default data SIM during the life cycle of the voice call.
+ * Controls whether mobile data on the non-default SIM is allowed during a voice call.
*
- * @param allow {@code true} if allowing using data during voice call, {@code false} if
- * disallowed.
+ * This is used for allowing data on the non-default data SIM when a voice call is placed on
+ * the non-default data SIM on DSDS devices. If this policy is disabled, users will not be able
+ * to use mobile data via the non-default data SIM during the call, which may mean no mobile
+ * data at all since some modem implementations disallow mobile data via the default data SIM
+ * during voice calls.
+ * If this policy is enabled, data will be temporarily enabled on the non-default data SIM
+ * during any voice calls.
*
- * @return {@code true} if operation is successful. otherwise {@code false}.
- *
- * @throws SecurityException if the caller doesn't have the permission.
- *
+ * This policy can be enabled and disabled via {@link #setMobileDataPolicyEnabledStatus}.
* @hide
*/
+ @SystemApi
+ @TestApi
+ public static final int MOBILE_DATA_POLICY_DATA_ON_NON_DEFAULT_DURING_VOICE_CALL = 1;
+
+ /**
+ * Controls whether MMS messages bypass the user-specified "mobile data" toggle.
+ *
+ * When enabled, requests for connections to the MMS APN will be accepted by telephony even if
+ * the user has turned "mobile data" off on this specific sim card. {@link #isDataEnabledForApn}
+ * will also return true for {@link ApnSetting#TYPE_MMS}.
+ * When disabled, the MMS APN will be governed by the same rules as all other APNs.
+ *
+ * This policy can be enabled and disabled via {@link #setMobileDataPolicyEnabledStatus}.
+ * @hide
+ */
+ @SystemApi
+ @TestApi
+ public static final int MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED = 2;
+
+ /**
+ * @hide
+ */
+ @IntDef(prefix = { "MOBILE_DATA_POLICY_" }, value = {
+ MOBILE_DATA_POLICY_DATA_ON_NON_DEFAULT_DURING_VOICE_CALL,
+ MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface MobileDataPolicy { }
+
+ /**
+ * Enables or disables a piece of mobile data policy.
+ *
+ * Enables or disables the mobile data policy specified in {@code policy}. See the detailed
+ * description of each policy constant for what they do.
+ *
+ * @param policy The data policy to enable.
+ * @param enabled Whether to enable or disable the policy.
+ * @hide
+ */
+ @SystemApi
+ @TestApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
- public boolean setDataAllowedDuringVoiceCall(boolean allow) {
+ public void setMobileDataPolicyEnabledStatus(@MobileDataPolicy int policy, boolean enabled) {
try {
ITelephony service = getITelephony();
if (service != null) {
- return service.setDataAllowedDuringVoiceCall(getSubId(), allow);
+ service.setMobileDataPolicyEnabledStatus(getSubId(), policy, enabled);
}
} catch (RemoteException ex) {
// This could happen if binder process crashes.
@@ -13312,27 +13352,23 @@
ex.rethrowAsRuntimeException();
}
}
- return false;
}
/**
- * Check whether data is allowed during voice call. This is used for allowing data on the
- * non-default data SIM. When a voice call is placed on the non-default data SIM on DSDS
- * devices, users will not be able to use mobile data. By calling this API, data will be
- * temporarily enabled on the non-default data SIM during the life cycle of the voice call.
+ * Fetches the status of a piece of mobile data policy.
*
- * @return {@code true} if data is allowed during voice call.
- *
- * @throws SecurityException if the caller doesn't have the permission.
- *
+ * @param policy The data policy that you want the status for.
+ * @return {@code true} if enabled, {@code false} otherwise.
* @hide
*/
+ @SystemApi
+ @TestApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- public boolean isDataAllowedInVoiceCall() {
+ public boolean isMobileDataPolicyEnabled(@MobileDataPolicy int policy) {
try {
ITelephony service = getITelephony();
if (service != null) {
- return service.isDataAllowedInVoiceCall(getSubId());
+ return service.isMobileDataPolicyEnabled(getSubId(), policy);
}
} catch (RemoteException ex) {
// This could happen if binder process crashes.
@@ -13344,31 +13380,6 @@
}
/**
- * Set whether the specific sim card always allows MMS connection. If true, MMS network
- * request will be accepted by telephony even if user turns "mobile data" off
- * on this specific sim card.
- *
- * @param alwaysAllow whether Mms data is always allowed.
- * @return whether operation is successful.
- *
- * @hide
- */
- @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
- public boolean setAlwaysAllowMmsData(boolean alwaysAllow) {
- try {
- ITelephony service = getITelephony();
- if (service != null) {
- return service.setAlwaysAllowMmsData(getSubId(), alwaysAllow);
- }
- } catch (RemoteException ex) {
- if (!isSystemProcess()) {
- ex.rethrowAsRuntimeException();
- }
- }
- return false;
- }
-
- /**
* The IccLock state or password was changed successfully.
* @hide
*/
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 53069a1..0d8351d 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -2164,21 +2164,9 @@
*/
String getMmsUAProfUrl(int subId);
- /**
- * Set allowing mobile data during voice call.
- */
- boolean setDataAllowedDuringVoiceCall(int subId, boolean allow);
+ void setMobileDataPolicyEnabledStatus(int subscriptionId, int policy, boolean enabled);
- /**
- * Check whether data is allowed during voice call. Note this is for dual sim device that
- * data might be disabled on non-default data subscription but explicitly turned on by settings.
- */
- boolean isDataAllowedInVoiceCall(int subId);
-
- /**
- * Set whether a subscription always allows MMS connection.
- */
- boolean setAlwaysAllowMmsData(int subId, boolean allow);
+ boolean isMobileDataPolicyEnabled(int subscriptionId, int policy);
/**
* Command line command to enable or disable handling of CEP data for test purposes.
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ColorFiltersMutateActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ColorFiltersMutateActivity.java
index 08144c8..b53b78a 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ColorFiltersMutateActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ColorFiltersMutateActivity.java
@@ -22,6 +22,7 @@
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
+import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
@@ -30,6 +31,7 @@
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.RuntimeShader;
+import android.graphics.Shader;
import android.os.Bundle;
import android.view.View;
@@ -59,9 +61,10 @@
private int mPorterDuffColor = 0;
static final String sSkSL =
- "uniform float param1;\n"
- + "void main(float2 xy, inout half4 color) {\n"
- + "color = half4(color.r, half(param1), color.b, 1.0);\n"
+ "in shader bitmapShader;\n"
+ + "uniform float param1;\n"
+ + "half4 main(float2 xy) {\n"
+ + " return half4(sample(bitmapShader, xy).rgb, param1);\n"
+ "}\n";
private byte[] mUniforms = new byte[4];
@@ -84,7 +87,9 @@
mBlendPaint.setColorFilter(new PorterDuffColorFilter(0, PorterDuff.Mode.SRC_OVER));
mShaderPaint = new Paint();
- mShaderPaint.setShader(new RuntimeShader(sSkSL, mUniforms, true));
+ Shader[] inputShaders = { new BitmapShader(mBitmap1, Shader.TileMode.CLAMP,
+ Shader.TileMode.CLAMP) };
+ mShaderPaint.setShader(new RuntimeShader(sSkSL, mUniforms, inputShaders, true));
setShaderParam1(0.0f);
ObjectAnimator sat = ObjectAnimator.ofFloat(this, "saturation", 1.0f);
diff --git a/tests/SilkFX/AndroidManifest.xml b/tests/SilkFX/AndroidManifest.xml
index 050e9c3..c30d761 100644
--- a/tests/SilkFX/AndroidManifest.xml
+++ b/tests/SilkFX/AndroidManifest.xml
@@ -4,9 +4,9 @@
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
-
+
http://www.apache.org/licenses/LICENSE-2.0
-
+
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -40,7 +40,14 @@
android:label="Glow Examples"/>
<activity android:name=".materials.GlassActivity"
- android:label="Glass Examples"/>
+ android:label="Glass Examples"
+ android:banner="@drawable/background1"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LEANBACK_LAUNCHER" />
+ </intent-filter>
+ </activity>
</application>
</manifest>
diff --git a/tests/SilkFX/res/layout-television/activity_glass.xml b/tests/SilkFX/res/layout-television/activity_glass.xml
new file mode 100644
index 0000000..1f566860
--- /dev/null
+++ b/tests/SilkFX/res/layout-television/activity_glass.xml
@@ -0,0 +1,302 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+** Copyright 2020, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+-->
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ tools:context=".MainActivity">
+
+ <ImageView
+ android:id="@+id/background"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:scaleType="matrix"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="parent"
+ tools:srcCompat="@drawable/background1" />
+
+ <com.android.test.silkfx.materials.GlassView
+ android:id="@+id/materialView"
+ android:layout_width="400dp"
+ android:layout_height="100dp"
+ android:layout_marginEnd="64dp"
+ android:layout_marginStart="64dp"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toEndOf="@id/background"
+ app:layout_constraintStart_toStartOf="@id/background"
+ app:layout_constraintTop_toTopOf="parent">
+ <TextView
+ android:id="@+id/textOverlay"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="18dp"
+ android:layout_gravity="center"
+ android:textColor="#ffffff"
+ android:text="Lorem Ipsum dolor sit amet." />
+ </com.android.test.silkfx.materials.GlassView>
+
+ <androidx.constraintlayout.widget.ConstraintLayout
+ android:id="@+id/bottomPanel"
+ android:layout_width="400dp"
+ android:layout_height="wrap_content"
+ android:background="?android:attr/colorBackground"
+ android:paddingTop="24dp"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent">
+
+ <SeekBar
+ android:id="@+id/materialOpacity"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="12dp"
+ android:layout_marginEnd="12dp"
+ android:layout_marginBottom="16dp"
+ android:max="100"
+ android:progress="12"
+ app:layout_constraintBottom_toTopOf="@+id/scrimOpacityTitle"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintHorizontal_bias="1.0"
+ app:layout_constraintStart_toStartOf="parent" />
+
+ <SeekBar
+ android:id="@+id/zoom"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="16dp"
+ android:layout_marginEnd="12dp"
+ android:layout_marginStart="12dp"
+ android:min="-100"
+ android:max="100"
+ android:progress="-15"
+ app:layout_constraintBottom_toTopOf="@+id/blurRadiusTitle"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintHorizontal_bias="1.0"
+ app:layout_constraintStart_toStartOf="parent" />
+
+ <SeekBar
+ android:id="@+id/blurRadius"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="16dp"
+ android:layout_marginEnd="12dp"
+ android:layout_marginStart="12dp"
+ android:max="150"
+ android:progress="40"
+ app:layout_constraintBottom_toTopOf="@+id/materialOpacityTitle"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintHorizontal_bias="1.0"
+ app:layout_constraintStart_toStartOf="parent" />
+
+ <SeekBar
+ android:id="@+id/scrimOpacity"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="12dp"
+ android:layout_marginEnd="12dp"
+ android:layout_marginBottom="16dp"
+ android:max="100"
+ android:progress="50"
+ app:layout_constraintBottom_toTopOf="@+id/noiseOpacityTitle"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintHorizontal_bias="1.0"
+ app:layout_constraintStart_toStartOf="parent" />
+
+ <SeekBar
+ android:id="@+id/noiseOpacity"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="12dp"
+ android:layout_marginEnd="12dp"
+ android:layout_marginBottom="24dp"
+ android:max="100"
+ android:progress="15"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintHorizontal_bias="0.0"
+ app:layout_constraintStart_toStartOf="parent" />
+
+ <TextView
+ android:id="@+id/scrimOpacityTitle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="24dp"
+ android:layout_marginBottom="8dp"
+ android:text="Scrim Opacity"
+ android:textColor="@android:color/white"
+ app:layout_constraintBottom_toTopOf="@+id/scrimOpacity"
+ app:layout_constraintStart_toStartOf="parent" />
+
+ <TextView
+ android:id="@+id/materialOpacityTitle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="24dp"
+ android:layout_marginBottom="8dp"
+ android:text="Soft light Opacity"
+ android:textColor="@android:color/white"
+ app:layout_constraintBottom_toTopOf="@+id/materialOpacity"
+ app:layout_constraintStart_toStartOf="parent" />
+
+ <TextView
+ android:id="@+id/zoomTitle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="24dp"
+ android:layout_marginBottom="8dp"
+ android:text="Zoom"
+ android:textColor="@android:color/white"
+ app:layout_constraintBottom_toTopOf="@+id/zoom"
+ app:layout_constraintStart_toStartOf="parent" />
+
+ <TextView
+ android:id="@+id/blurRadiusTitle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="24dp"
+ android:layout_marginBottom="8dp"
+ android:text="Blur Radius"
+ android:textColor="@android:color/white"
+ app:layout_constraintBottom_toTopOf="@+id/blurRadius"
+ app:layout_constraintStart_toStartOf="parent" />
+
+ <TextView
+ android:id="@+id/noiseOpacityTitle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="24dp"
+ android:layout_marginBottom="8dp"
+ android:textColor="@android:color/white"
+ android:text="Noise Opacity"
+ app:layout_constraintBottom_toTopOf="@+id/noiseOpacity"
+ app:layout_constraintStart_toStartOf="parent" />
+
+ <ImageView
+ android:id="@+id/background1"
+ android:layout_width="64dp"
+ android:layout_height="64dp"
+ android:layout_marginStart="24dp"
+ android:layout_marginBottom="16dp"
+ android:foreground="?android:attr/selectableItemBackgroundBorderless"
+ android:clickable="true"
+ android:onClick="onBackgroundClick"
+ android:scaleType="centerCrop"
+ app:layout_constraintBottom_toTopOf="@+id/lightMaterialSwitch"
+ app:layout_constraintStart_toStartOf="parent"
+ android:src="@drawable/background1" />
+
+ <ImageView
+ android:id="@+id/background2"
+ android:layout_width="64dp"
+ android:layout_height="64dp"
+ android:layout_marginStart="8dp"
+ android:foreground="?android:attr/selectableItemBackgroundBorderless"
+ android:clickable="true"
+ android:onClick="onBackgroundClick"
+ android:scaleType="centerCrop"
+ app:layout_constraintBottom_toBottomOf="@+id/background1"
+ app:layout_constraintStart_toEndOf="@+id/background1"
+ android:src="@drawable/background2" />
+
+ <ImageView
+ android:id="@+id/background3"
+ android:layout_width="64dp"
+ android:layout_height="64dp"
+ android:layout_marginStart="8dp"
+ android:scaleType="centerCrop"
+ android:foreground="?android:attr/selectableItemBackgroundBorderless"
+ android:clickable="true"
+ android:onClick="onBackgroundClick"
+ app:layout_constraintBottom_toBottomOf="@+id/background1"
+ app:layout_constraintStart_toEndOf="@+id/background2"
+ android:src="@drawable/background3" />
+
+ <Button
+ android:id="@+id/pickImage"
+ android:layout_width="64dp"
+ android:layout_height="64dp"
+ android:layout_marginStart="8dp"
+ android:scaleType="centerCrop"
+ android:foreground="?android:attr/selectableItemBackgroundBorderless"
+ android:clickable="true"
+ android:onClick="onPickImageClick"
+ app:layout_constraintBottom_toBottomOf="@+id/background1"
+ app:layout_constraintStart_toEndOf="@+id/background3"
+ android:text="Pick file" />
+
+ <Switch
+ android:id="@+id/lightMaterialSwitch"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="24dp"
+ android:layout_marginBottom="8dp"
+ android:text="Light Material"
+ app:layout_constraintBottom_toTopOf="@+id/zoomTitle"
+ app:layout_constraintStart_toStartOf="parent" />
+
+ <TextView
+ android:id="@+id/blurRadiusValue"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="TextView"
+ android:layout_marginLeft="8dp"
+ app:layout_constraintBottom_toBottomOf="@+id/blurRadiusTitle"
+ app:layout_constraintStart_toEndOf="@+id/blurRadiusTitle" />
+
+ <TextView
+ android:id="@+id/zoomValue"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="TextView"
+ android:layout_marginLeft="8dp"
+ app:layout_constraintBottom_toBottomOf="@+id/zoomTitle"
+ app:layout_constraintStart_toEndOf="@+id/zoomTitle" />
+
+ <TextView
+ android:id="@+id/materialOpacityValue"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="TextView"
+ android:layout_marginLeft="8dp"
+ app:layout_constraintBottom_toBottomOf="@+id/materialOpacityTitle"
+ app:layout_constraintStart_toEndOf="@+id/materialOpacityTitle" />
+
+ <TextView
+ android:id="@+id/noiseOpacityValue"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="TextView"
+ android:layout_marginLeft="8dp"
+ app:layout_constraintBottom_toBottomOf="@+id/noiseOpacityTitle"
+ app:layout_constraintStart_toEndOf="@+id/noiseOpacityTitle" />
+
+
+ <TextView
+ android:id="@+id/scrimOpacityValue"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="TextView"
+ android:layout_marginLeft="8dp"
+ app:layout_constraintBottom_toBottomOf="@+id/scrimOpacityTitle"
+ app:layout_constraintStart_toEndOf="@+id/scrimOpacityTitle" />
+
+ </androidx.constraintlayout.widget.ConstraintLayout>
+
+
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java
index c895420..85704d0 100644
--- a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java
+++ b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java
@@ -213,7 +213,7 @@
public void connect() {
assertNotEquals("MockNetworkAgents can only be connected once",
- getNetworkInfo().getDetailedState(), NetworkInfo.DetailedState.CONNECTED);
+ mNetworkInfo.getDetailedState(), NetworkInfo.DetailedState.CONNECTED);
mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null);
mNetworkAgent.sendNetworkInfo(mNetworkInfo);
}
@@ -268,10 +268,6 @@
return mNetworkAgent;
}
- public NetworkInfo getNetworkInfo() {
- return mNetworkInfo;
- }
-
public NetworkCapabilities getNetworkCapabilities() {
return mNetworkCapabilities;
}
diff --git a/tests/net/java/android/net/util/IpUtilsTest.java b/tests/net/java/android/net/util/IpUtilsTest.java
deleted file mode 100644
index 193d85d..0000000
--- a/tests/net/java/android/net/util/IpUtilsTest.java
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.util;
-
-import static org.junit.Assert.assertEquals;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.nio.ByteBuffer;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class IpUtilsTest {
-
- private static final int IPV4_HEADER_LENGTH = 20;
- private static final int IPV6_HEADER_LENGTH = 40;
- private static final int TCP_HEADER_LENGTH = 20;
- private static final int UDP_HEADER_LENGTH = 8;
- private static final int IP_CHECKSUM_OFFSET = 10;
- private static final int TCP_CHECKSUM_OFFSET = 16;
- private static final int UDP_CHECKSUM_OFFSET = 6;
-
- private int getUnsignedByte(ByteBuffer buf, int offset) {
- return buf.get(offset) & 0xff;
- }
-
- private int getChecksum(ByteBuffer buf, int offset) {
- return getUnsignedByte(buf, offset) * 256 + getUnsignedByte(buf, offset + 1);
- }
-
- private void assertChecksumEquals(int expected, short actual) {
- assertEquals(Integer.toHexString(expected), Integer.toHexString(actual & 0xffff));
- }
-
- // Generate test packets using Python code like this::
- //
- // from scapy import all as scapy
- //
- // def JavaPacketDefinition(bytes):
- // out = " ByteBuffer packet = ByteBuffer.wrap(new byte[] {\n "
- // for i in xrange(len(bytes)):
- // out += "(byte) 0x%02x" % ord(bytes[i])
- // if i < len(bytes) - 1:
- // if i % 4 == 3:
- // out += ",\n "
- // else:
- // out += ", "
- // out += "\n });"
- // return out
- //
- // packet = (scapy.IPv6(src="2001:db8::1", dst="2001:db8::2") /
- // scapy.UDP(sport=12345, dport=7) /
- // "hello")
- // print JavaPacketDefinition(str(packet))
-
- @Test
- public void testIpv6TcpChecksum() throws Exception {
- // packet = (scapy.IPv6(src="2001:db8::1", dst="2001:db8::2", tc=0x80) /
- // scapy.TCP(sport=12345, dport=7,
- // seq=1692871236, ack=128376451, flags=16,
- // window=32768) /
- // "hello, world")
- ByteBuffer packet = ByteBuffer.wrap(new byte[] {
- (byte) 0x68, (byte) 0x00, (byte) 0x00, (byte) 0x00,
- (byte) 0x00, (byte) 0x20, (byte) 0x06, (byte) 0x40,
- (byte) 0x20, (byte) 0x01, (byte) 0x0d, (byte) 0xb8,
- (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
- (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
- (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01,
- (byte) 0x20, (byte) 0x01, (byte) 0x0d, (byte) 0xb8,
- (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
- (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
- (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x02,
- (byte) 0x30, (byte) 0x39, (byte) 0x00, (byte) 0x07,
- (byte) 0x64, (byte) 0xe7, (byte) 0x2a, (byte) 0x44,
- (byte) 0x07, (byte) 0xa6, (byte) 0xde, (byte) 0x83,
- (byte) 0x50, (byte) 0x10, (byte) 0x80, (byte) 0x00,
- (byte) 0xee, (byte) 0x71, (byte) 0x00, (byte) 0x00,
- (byte) 0x68, (byte) 0x65, (byte) 0x6c, (byte) 0x6c,
- (byte) 0x6f, (byte) 0x2c, (byte) 0x20, (byte) 0x77,
- (byte) 0x6f, (byte) 0x72, (byte) 0x6c, (byte) 0x64
- });
-
- // Check that a valid packet has checksum 0.
- int transportLen = packet.limit() - IPV6_HEADER_LENGTH;
- assertEquals(0, IpUtils.tcpChecksum(packet, 0, IPV6_HEADER_LENGTH, transportLen));
-
- // Check that we can calculate the checksum from scratch.
- int sumOffset = IPV6_HEADER_LENGTH + TCP_CHECKSUM_OFFSET;
- int sum = getUnsignedByte(packet, sumOffset) * 256 + getUnsignedByte(packet, sumOffset + 1);
- assertEquals(0xee71, sum);
-
- packet.put(sumOffset, (byte) 0);
- packet.put(sumOffset + 1, (byte) 0);
- assertChecksumEquals(sum, IpUtils.tcpChecksum(packet, 0, IPV6_HEADER_LENGTH, transportLen));
-
- // Check that writing the checksum back into the packet results in a valid packet.
- packet.putShort(
- sumOffset,
- IpUtils.tcpChecksum(packet, 0, IPV6_HEADER_LENGTH, transportLen));
- assertEquals(0, IpUtils.tcpChecksum(packet, 0, IPV6_HEADER_LENGTH, transportLen));
- }
-
- @Test
- public void testIpv4UdpChecksum() {
- // packet = (scapy.IP(src="192.0.2.1", dst="192.0.2.2", tos=0x40) /
- // scapy.UDP(sport=32012, dport=4500) /
- // "\xff")
- ByteBuffer packet = ByteBuffer.wrap(new byte[] {
- (byte) 0x45, (byte) 0x40, (byte) 0x00, (byte) 0x1d,
- (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00,
- (byte) 0x40, (byte) 0x11, (byte) 0xf6, (byte) 0x8b,
- (byte) 0xc0, (byte) 0x00, (byte) 0x02, (byte) 0x01,
- (byte) 0xc0, (byte) 0x00, (byte) 0x02, (byte) 0x02,
- (byte) 0x7d, (byte) 0x0c, (byte) 0x11, (byte) 0x94,
- (byte) 0x00, (byte) 0x09, (byte) 0xee, (byte) 0x36,
- (byte) 0xff
- });
-
- // Check that a valid packet has IP checksum 0 and UDP checksum 0xffff (0 is not a valid
- // UDP checksum, so the udpChecksum rewrites 0 to 0xffff).
- assertEquals(0, IpUtils.ipChecksum(packet, 0));
- assertEquals((short) 0xffff, IpUtils.udpChecksum(packet, 0, IPV4_HEADER_LENGTH));
-
- // Check that we can calculate the checksums from scratch.
- final int ipSumOffset = IP_CHECKSUM_OFFSET;
- final int ipSum = getChecksum(packet, ipSumOffset);
- assertEquals(0xf68b, ipSum);
-
- packet.put(ipSumOffset, (byte) 0);
- packet.put(ipSumOffset + 1, (byte) 0);
- assertChecksumEquals(ipSum, IpUtils.ipChecksum(packet, 0));
-
- final int udpSumOffset = IPV4_HEADER_LENGTH + UDP_CHECKSUM_OFFSET;
- final int udpSum = getChecksum(packet, udpSumOffset);
- assertEquals(0xee36, udpSum);
-
- packet.put(udpSumOffset, (byte) 0);
- packet.put(udpSumOffset + 1, (byte) 0);
- assertChecksumEquals(udpSum, IpUtils.udpChecksum(packet, 0, IPV4_HEADER_LENGTH));
-
- // Check that writing the checksums back into the packet results in a valid packet.
- packet.putShort(ipSumOffset, IpUtils.ipChecksum(packet, 0));
- packet.putShort(udpSumOffset, IpUtils.udpChecksum(packet, 0, IPV4_HEADER_LENGTH));
- assertEquals(0, IpUtils.ipChecksum(packet, 0));
- assertEquals((short) 0xffff, IpUtils.udpChecksum(packet, 0, IPV4_HEADER_LENGTH));
- }
-}
diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java
index 7ab4d97..bc3db11 100644
--- a/tests/net/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/net/java/com/android/server/connectivity/VpnTest.java
@@ -1155,7 +1155,7 @@
new String[] { EGRESS_IFACE, "l2tp", expectedAddr, "1701", profile.l2tpSecret,
"name", profile.username, "password", profile.password,
"linkname", "vpn", "refuse-eap", "nodefaultroute", "usepeerdns",
- "idle", "1800", "mtu", "1400", "mru", "1400" },
+ "idle", "1800", "mtu", "1270", "mru", "1270" },
deps.mtpdArgs.get(10, TimeUnit.SECONDS));
// Now wait for the runner to be ready before testing for the route.
legacyRunnerReady.block(10_000);
diff --git a/tests/vcn/OWNERS b/tests/vcn/OWNERS
new file mode 100644
index 0000000..33b9f0f
--- /dev/null
+++ b/tests/vcn/OWNERS
@@ -0,0 +1,7 @@
+set noparent
+
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
\ No newline at end of file
diff --git a/tools/codegen/src/com/android/codegen/Generators.kt b/tools/codegen/src/com/android/codegen/Generators.kt
index 5a96cf1..6e1ab59 100644
--- a/tools/codegen/src/com/android/codegen/Generators.kt
+++ b/tools/codegen/src/com/android/codegen/Generators.kt
@@ -3,7 +3,10 @@
import com.github.javaparser.ast.body.FieldDeclaration
import com.github.javaparser.ast.body.MethodDeclaration
import com.github.javaparser.ast.body.VariableDeclarator
-import com.github.javaparser.ast.expr.*
+import com.github.javaparser.ast.expr.AnnotationExpr
+import com.github.javaparser.ast.expr.ArrayInitializerExpr
+import com.github.javaparser.ast.expr.LiteralExpr
+import com.github.javaparser.ast.expr.UnaryExpr
import java.io.File
@@ -703,7 +706,7 @@
generateFieldJavadoc(forceHide = FeatureFlag.SETTERS.hidden)
+GENERATED_MEMBER_HEADER
- "public $ClassType set$NameUpperCamel($annotatedTypeForSetterParam value)" {
+ "public @$NonNull $ClassType set$NameUpperCamel($annotatedTypeForSetterParam value)" {
generateSetFrom("value")
+"return this;"
}
diff --git a/tools/codegen/src/com/android/codegen/SharedConstants.kt b/tools/codegen/src/com/android/codegen/SharedConstants.kt
index 36070b5..785aa910 100644
--- a/tools/codegen/src/com/android/codegen/SharedConstants.kt
+++ b/tools/codegen/src/com/android/codegen/SharedConstants.kt
@@ -1,7 +1,7 @@
package com.android.codegen
const val CODEGEN_NAME = "codegen"
-const val CODEGEN_VERSION = "1.0.16"
+const val CODEGEN_VERSION = "1.0.17"
const val CANONICAL_BUILDER_CLASS = "Builder"
const val BASE_BUILDER_CLASS = "BaseBuilder"
diff --git a/wifi/jarjar-rules.txt b/wifi/jarjar-rules.txt
index e253ae2..eef08b5 100644
--- a/wifi/jarjar-rules.txt
+++ b/wifi/jarjar-rules.txt
@@ -70,7 +70,6 @@
rule android.net.util.InterfaceParams* com.android.wifi.x.@0
rule android.net.util.SharedLog* com.android.wifi.x.@0
rule android.net.util.NetUtils* com.android.wifi.x.@0
-rule android.net.util.IpUtils* com.android.wifi.x.@0
rule androidx.annotation.** com.android.wifi.x.@0